####

Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

Motivation


According to a recent report, overall tobacco use increased in youths (middle schooland high school students) in the United States in 2017 and 2018, despite previous years of declining use.

This major increase is attributed to an increase in the use of electronic cigaarette (e-cigarette) products.

E-cigarettes are referred to by many different names, including but not limited to:

  1. Electronic nicotine delivery systems (ENDS)
  2. Vapes
  3. e-hookahs
  4. vape pens
  5. tanks
  6. mods

The devices vary greatly:

[source]

See this CDC guide and the American Lung Association website for more information.

The report found that:

During 2017–2018, current use of any tobacco product increased 38.3% (from 19.6% to 27.1%) among high school students and 28.6% (from 5.6% to 7.2%) among middle school students; e-cigarette use increased 77.8% (from 11.7% to 20.8%) among high school students and 48.5% (from 3.3% to 4.9%) among middle school students.

In 2018, the Federal Drug Administration (FDA) in the United States stated that e-cigarette usage use among youth reached:

“nothing short of an epidemic proportion of growth

In this case study, we will be invistigating the same data used in the report that generated the above findings. This data comes from the The National Youth Tobacco Survey (NYTS).

Gentzke, Andrea S., Melisa Creamer, Karen A. Cullen, Bridget K. Ambrose, Gordon Willis, Ahmed Jamal, and Brian A. King. “Vital Signs: Tobacco Product Use Among Middle and High School Students - United States, 2011-2018.” MMWR. Morbidity and Mortality Weekly Report 68 (6): 157–64 (2019).

Main Questions


Our main question:

  1. How has tobacco/nicotine use by American youths changed since 2015?
  2. How do vaping rates compare between males and females?
  3. What vaping brands and flavors appear to be used the most frequently?
    We will base this on the following survey questions:
    > “During the past 30 days, what brand of e-cigarettes did you usually use?”
    >“What flavors of tobacco products have you used in the past 30 days?”

  4. Have vaping rates possibly influenced tobacco/nicotine use?

Learning Objectives


In this case study, we will cover how to import data from multiple files efficiently, how to import data from excel files, and how to make a variety of visualizations to compare multiple groups across time. We will also demonstrate how to work with codebooks. We will cover the concept of survey weighting and introduce the srvyr package. We will discuss the difference between pooled cross-sectional data and panel data. We will especially focus on using packages and functions from the Tidyverse for wrangling data, such as tidyr and dpyr and for visualization, such as as ggplot2. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.


We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
readxl to import the data in the excel files
purrr to import the data in all the different excel and csv files efficiently
readr to import the CSV file data
dplyr to arrange/filter/select/compare specific subsets of the data
summarytools to get an overview of data in a different style
tidyr to rearrange data in wide and long formats

stringr | to manipulate the character strings within the data
ggplot2 | to make visualizations with multiple layers
ggpubr | to easily add regression line equations to plots
forcats | to change details about factors (categorical variables)
lmerTest| to perform linear mixed model testing
car| to perform Levene’s Test of Homogeneity of Variances
ggiraph| to make plots interactive
ggforce| to modify facets in plots
viridis| to plot in color palette
cowplot | to allow plots to be combined skimr | to get an overview of data

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


According to the cited Morbidity and Mortality Weekly Report this was what was already known about this topic and the implications of this study:

Importantly, the vapors used in e-cigarettes contain harmful chemicals:

E-cigarette usage has also been associated with lung injury

See here for additonal information about the potential health effects of e-cigarettes in teens and young adults.

Limitations


There are some important considerations regarding this data analysis to keep in mind:

AVOCADO..Need Michael to look at these…

  1. The data included in the National Youth Tobacco Survey (NYTS) does not follow the same individual students over time. A longitudinal study that does follow the same individuals over time collects data called panel data. The data in this study is called pooled [cross-sectional data]https://en.wikipedia.org/wiki/Cross-sectional_data, this data is obtained from random collection of obervations across time.

According to wikipedia: >Panel data differs from pooled cross-sectional data across time, because it deals with the observations on the same subjects in different times whereas the latter observes different subjects in different time periods

AVOCADO revisit this… 2) The data also includes percentages of students that reported use of particular tobacco product, but the survey questions did not ask how much uses of one product compared to another - for example menthol flavored products where used at the near exclusion of other flavors.

While gender and sex are not actually binary, the data used in this analysis only contains information for groups of individuals who answered the survey questions as male or female.

AVOCADO.. should we drop the race data? we didnt use it… Furthermore, while the race of individual students was surveyed and asked students to self report based on what race or races they considered themselves to be, this list only included the following options:
1) Hispanic, Latino, Latina, or Spanish origin as one single race with the following further options:
1) Mexican, Mexican American, Chicano, or Chicana
2) Puerto Rican
3) Cuban
4) Yes, Another Hispanic, Latino, Latina, or Spanish origin
2)

What are the data?


The data in this case study comes from the National Youth Tobacco Survey (NYTS) which is an annual survey that asks students in high school and middle school (grades 6-12) about tobacco usage in the United States of America.

The data for this survey is freely available online at this website with data from 1999, 2000, 2002, 2004, 2006, 2009, and 2011-2019. We will be using data from 2015-2019 due to the fact that these years are the most recent that asked questions recarding e-cigarette usage.

Each year includes documentation, such as a codebook and an excel file containing the data:

Therefore, since we are using data from 2015-2019, the data we are interested in is located in 5 different excel files, each with their own codebook.

The codebook contains information describing the data within the excel file.

As you can see the excel file contains very short variable names and values, and it is not clear what they mean without the codebook:

The codebook explains what the variables (the columns) are:

And the codebook explains what the values for each variable are:

We will explain more later about what the values on the right indicate.

The reason that there are codebooks for each year is because the questions asked year varied slightly.

The data in this survey is what is called pooled cross-sectional data. In otherwords, different subsets of students are surveyed each year and it is not clear which, if any , individuals particpate from one year to the next.

Data Import


Reading in the excel files


Since these excel files are so large, it takes a bit of time for the data to load. To make the process faster, we previously imported these files, selected only our questions of interest, and saved this data as csv files.

AVOCADO should we drop the race data? we didn’t end up doing anything with this….

Click here for details on how the data was originally imported

First we created a list of filenames of all the different excel files. Using the here() function of the here package, we looked in all the directories of the project. The list.files() function looked for all files with .xlsx within these subdirectories.

[1] "docs/2015-nyts-dataset-and-codebook-microsoft-excel/nyts2015.xlsx"
[2] "docs/2016-nyts-dataset-and-codebook-microsoft-excel/nyts2016.xlsx"
[3] "docs/2017-nyts-dataset-and-codebook-microsoft-excel/nyts2017.xlsx"
[4] "docs/2018-nyts-dataset-and-codebook-microsoft-excel/nyts2018.xlsx"
[5] "docs/2019-nyts-dataset-and-codebook-microsoft-excel/nyts2019.xlsx"

All the files were read using read_excel of the readxl package.Using the map() function of the purrr package this was done efficiently. This created a single list of tibbles (one for each file).

Each excel file name was extracted using the str_extract() function of the stringr package.

[1] "nyts2015" "nyts2016" "nyts2017" "nyts2018" "nyts2019"

These names became the names of the tibbles in the list of tibbles.

Specific columns were selected from each of the tibbles using the varaible name, as identified in the codebook for being of interest. In some cases functions like starts_with() of the dplyr package were used to select several variables.

tbl[["nyts2015"]] <- tbl[["nyts2015"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Qn1, #Age
                  Qn2, #Sex
                  Qn3, #Grade
                  starts_with("Qn4"), #Hispanic/Latino
                  starts_with("Qn5"), #Race,
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  EFLAVCIGTS,
                  CFLAVCIGTS,
                  EFLAVCIGAR,
                  )

tbl[["nyts2016"]] <- tbl[["nyts2016"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  EFLAVCIGAR,
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  ) 

tbl[["nyts2017"]] <- tbl[["nyts2017"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  CBIDIS,
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  )

tbl[["nyts2018"]] <- tbl[["nyts2018"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  )

tbl[["nyts2019"]] <- tbl[["nyts2019"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  EHTP,
                  CHTP,
                  Q40, #Brang, e-cigarettes
                  Q62A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q62B, #Clove or spice
                  Q62C, #Fruit 
                  Q62D, #Chocolate
                  Q62E, #Alcoholic Drink
                  Q62F, #Candy/Desserts/Other Sweets
                  Q62G, #Some Other Flavor Not Listed Here 
                  )

A directory was created using the base dir.create() function called data_reduced for the csv files. New csv files were created for each of the tbls in the list using the write_csv() function of the readr package. This was done all at once using the base mappy() function.

Now we will show how to read in the data from the five csv files that were created from the five different excel files.

Data Exploration and Wrangling


Renaming variables


Here is what the data for 2015 looks like: #### {.scrollable }

Rows: 17,711
Columns: 110
$ psu        <chr> "015438", "015438", "015438", "015438", "015438", "015438"…
$ finwgt     <dbl> 216.7268, 324.9620, 324.9620, 397.1552, 264.8745, 264.8745…
$ stratum    <chr> "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "B…
$ Qn1        <dbl> 10, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,…
$ Qn2        <dbl> 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2…
$ Qn3        <dbl> 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5…
$ Qn4a       <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
$ Qn4b       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn4c       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn4d       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn4e       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40a      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40b      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40c      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40d      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40e      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40f      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40g      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn40h      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
$ Qn41a      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41b      <dbl> NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Qn41c      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41d      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41e      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41f      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41g      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41h      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41i      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn41j      <dbl> 1, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ Qn42       <dbl> 11, 1, 11, 1, 11, 1, 4, 1, 11, 11, 11, 3, 11, 11, 11, 1, 1…
$ Qn43a      <dbl> 1, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ Qn43b      <dbl> NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Qn43c      <dbl> NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Qn43d      <dbl> NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Qn43e      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn43f      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn43g      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn43h      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn44a      <dbl> 1, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ Qn44b      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn44c      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn44d      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn44e      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn44f      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn44g      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn44h      <dbl> NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Qn45a      <dbl> 1, NA, 1, NA, 1, NA, NA, NA, 1, 1, 1, NA, 1, 1, 1, 1, 1, 1…
$ Qn45b      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn45c      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn45d      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn45e      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn45f      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn45g      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn45h      <dbl> NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Qn45i      <dbl> NA, NA, NA, NA, NA, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA, …
$ Qn45j      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn45k      <dbl> NA, NA, NA, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Qn46       <dbl> 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, 1, …
$ Qn47       <dbl> 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ Qn48       <dbl> 1, 1, 1, 1, 1, 1, 6, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, 1, …
$ Qn49       <dbl> 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1…
$ Qn5a       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn5b       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn5c       <dbl> 1, 1, 1, NA, NA, NA, NA, NA, 1, 1, 1, NA, 1, 1, 1, NA, 1, …
$ Qn5d       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn5e       <dbl> NA, NA, NA, 1, 1, 1, 1, 1, NA, NA, NA, 1, NA, NA, NA, 1, N…
$ Qn50       <dbl> 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1…
$ Qn51       <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
$ Qn52       <dbl> 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1…
$ Qn53       <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
$ Qn54       <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1…
$ Qn55a      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, 1, …
$ Qn55b      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55c      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55d      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55e      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55f      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55g      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55h      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55i      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55j      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55k      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn55l      <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ Qn56       <dbl> 3, 4, 4, 3, 4, 3, 2, 4, 3, 4, 2, 4, 4, 4, 4, 4, 3, 4, 4, 3…
$ Qn57       <dbl> 3, 4, 4, 3, 4, 3, 3, 4, 3, 4, 3, 4, 2, 4, 4, 4, 4, 4, 3, 3…
$ Qn58       <dbl> 4, 4, 4, 3, 4, 3, 3, 4, 3, 4, 3, 4, 4, 4, 4, 3, 4, 4, 4, 4…
$ Qn59       <dbl> 3, 1, 4, 2, 4, 3, 2, 3, 3, 4, 2, 4, 2, 4, 4, 2, 4, 3, 2, 2…
$ ECIGT      <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1…
$ ECIGAR     <dbl> 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2…
$ ESLT       <dbl> 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EELCIGT    <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1…
$ EROLLCIGTS <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2…
$ EFLAVCIGTS <dbl> 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EBIDIS     <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EFLAVCIGAR <dbl> 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 2…
$ EHOOKAH    <dbl> 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EPIPE      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ ESNUS      <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ EDISSOLV   <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CCIGT      <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CCIGAR     <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CSLT       <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CELCIGT    <dbl> 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CROLLCIGTS <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CFLAVCIGTS <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CBIDIS     <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CHOOKAH    <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CPIPE      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CSNUS      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ CDISSOLV   <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…

Rows: 17,711
Columns: 48
$ psu                  <chr> "015438", "015438", "015438", "015438", "015438"…
$ finwgt               <dbl> 216.7268, 324.9620, 324.9620, 397.1552, 264.8745…
$ stratum              <chr> "BR3", "BR3", "BR3", "BR3", "BR3", "BR3", "BR3",…
$ Age                  <dbl> 18, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, …
$ female               <dbl> 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 1, …
$ Grade                <dbl> 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, …
$ Not_HL               <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ HL_Mex               <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ HL_PR                <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ HL_Cub               <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ HL_Other             <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ Race_AIAN            <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ Race_Asian           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ Race_BAA             <dbl> 1, 1, 1, NA, NA, NA, NA, NA, 1, 1, 1, NA, 1, 1, …
$ Race_NHOPI           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ Race_White           <dbl> NA, NA, NA, 1, 1, 1, 1, 1, NA, NA, NA, 1, NA, NA…
$ ECIGT                <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, …
$ ECIGAR               <dbl> 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ ESLT                 <dbl> 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EELCIGT              <dbl> 2, 1, 2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, …
$ EROLLCIGTS           <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, …
$ EFLAVCIGTS           <dbl> 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EBIDIS               <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EFLAVCIGAR           <dbl> 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, …
$ EHOOKAH              <dbl> 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EPIPE                <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ ESNUS                <dbl> 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ EDISSOLV             <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CCIGT                <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CCIGAR               <dbl> 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CSLT                 <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CELCIGT              <dbl> 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CROLLCIGTS           <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CFLAVCIGTS           <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CBIDIS               <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CHOOKAH              <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CPIPE                <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CSNUS                <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ CDISSOLV             <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ brand_ecig           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ menthol              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ clove_spice          <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ fruit                <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ chocolate            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ alcoholic_drink      <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ candy_dessert_sweets <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ other                <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ no_use               <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
Data summary
Name nyts_data[[“nyts2015”]]
Number of rows 17711
Number of columns 48
_______________________
Column type frequency:
character 2
logical 9
numeric 37
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
psu 0 1 6 6 0 82 0
stratum 0 1 3 3 0 16 0

Variable type: logical

skim_variable n_missing complete_rate mean count
brand_ecig 17711 0 NaN :
menthol 17711 0 NaN :
clove_spice 17711 0 NaN :
fruit 17711 0 NaN :
chocolate 17711 0 NaN :
alcoholic_drink 17711 0 NaN :
candy_dessert_sweets 17711 0 NaN :
other 17711 0 NaN :
no_use 17711 0 NaN :

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
finwgt 0 1.00 1539.67 1199.32 31.52 814.04 1194.16 1792.16 6084.76 ▇▅▁▁▁
Age 69 1.00 14.53 2.04 9.00 13.00 14.00 16.00 19.00 ▂▇▇▇▂
female 131 0.99 1.49 0.50 1.00 1.00 1.00 2.00 2.00 ▇▁▁▁▇
Grade 90 0.99 8.85 1.96 6.00 7.00 9.00 11.00 13.00 ▇▅▇▃▃
Not_HL 5400 0.70 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
HL_Mex 14975 0.15 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
HL_PR 17175 0.03 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
HL_Cub 17450 0.01 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
HL_Other 16073 0.09 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
Race_AIAN 16559 0.07 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
Race_Asian 16688 0.06 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
Race_BAA 14111 0.20 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
Race_NHOPI 17218 0.03 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
Race_White 6858 0.61 1.00 0.00 1.00 1.00 1.00 1.00 1.00 ▁▁▇▁▁
ECIGT 317 0.98 1.79 0.41 1.00 2.00 2.00 2.00 2.00 ▂▁▁▁▇
ECIGAR 414 0.98 1.83 0.37 1.00 2.00 2.00 2.00 2.00 ▂▁▁▁▇
ESLT 358 0.98 1.92 0.27 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
EELCIGT 311 0.98 1.73 0.44 1.00 1.00 2.00 2.00 2.00 ▃▁▁▁▇
EROLLCIGTS 715 0.96 1.95 0.22 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
EFLAVCIGTS 715 0.96 1.95 0.22 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
EBIDIS 715 0.96 1.99 0.12 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
EFLAVCIGAR 715 0.96 1.91 0.28 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
EHOOKAH 715 0.96 1.87 0.34 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
EPIPE 715 0.96 1.98 0.15 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
ESNUS 715 0.96 1.98 0.15 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
EDISSOLV 715 0.96 1.99 0.09 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CCIGT 364 0.98 1.94 0.24 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CCIGAR 543 0.97 1.94 0.23 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CSLT 328 0.98 1.97 0.18 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CELCIGT 270 0.98 1.89 0.32 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CROLLCIGTS 767 0.96 1.98 0.15 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CFLAVCIGTS 767 0.96 1.98 0.15 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CBIDIS 767 0.96 1.99 0.07 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CHOOKAH 767 0.96 1.95 0.22 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CPIPE 767 0.96 1.99 0.09 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CSNUS 767 0.96 1.99 0.09 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
CDISSOLV 767 0.96 2.00 0.06 1.00 2.00 2.00 2.00 2.00 ▁▁▁▁▇
####

Reminder: Current users are a subset of ever users.

We will also use the %>% pipe which can be used to define the input for later sequential steps. This will make more sense when we have multiple sequential steps using the same data object. To use the pipe notation we need to install and load dplyr as well.

Data Visualization


Question 1

For lots of pivot_longer() that are the same… can use pivot_longer_spec()

spec <- relig_income %>% build_longer_spec( cols = -religion, names_to = “income”, values_to = “count” ) pivot_longer_spec(relig_income, spec)

But need to decide if we are going to create some new data frames…

Question 3

What vaping brands and flavors appear to be used the most frequently?

Huang J, Duan Z, Kwok J, et al. Tob Control 2019;28:146–151.

Huang J, Duan Z, Kwok J, et al. Tob Control 2019;28:146–151.

Paper

plot5 <- nyts_data %>%
  filter(year!=2015) %>%
  filter(menthol==TRUE|
           clove_spice==TRUE|
           fruit==TRUE|
           chocolate==TRUE|
           alcoholic_drink==TRUE|
           candy_dessert_sweets==TRUE|
           other==TRUE) %>%
  mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  mutate(ecig_only_ever = case_when(ecig_ever == TRUE &
                                      non_ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           ecig_only_current = case_when(ecig_current == TRUE &
                                           non_ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           non_ecig_only_ever = case_when(non_ecig_ever == TRUE &
                                            ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           non_ecig_only_current = case_when(non_ecig_current == TRUE &
                                               ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE)) %>%
  mutate(Group = case_when(ecig_only_ever==TRUE |
                             ecig_only_current==TRUE ~ "Only e-cigarettes",
                         non_ecig_only_ever==TRUE |
                           non_ecig_only_current==TRUE ~ "Only other products",
                                    TRUE ~ "Both")) %>%
  filter(Group!="Both") %>%
  group_by(year, Group) %>%
  summarise(`Menthol`=(sum(menthol, na.rm = TRUE)*100)/
              sum(!is.na(menthol)),
              `Clove or Spice`=(sum(clove_spice, na.rm = TRUE)*100)/
              sum(!is.na(clove_spice)),
              `Fruit`=(sum(fruit, na.rm = TRUE)*100)/sum(!is.na(fruit)),
              `Chocolate`=(sum(chocolate, na.rm = TRUE)*100)/
              sum(!is.na(chocolate)),
              `Alcoholic Drink`=(sum(alcoholic_drink, na.rm = TRUE)*100)/
              sum(!is.na(alcoholic_drink)),
              `Candy/Desserts/Sweets`=(sum(candy_dessert_sweets, na.rm = TRUE)*100)/
              sum(!is.na(candy_dessert_sweets)),
            `Other`=(sum(other, na.rm = TRUE)*100)/
              sum(!is.na(other)),
            Respondents=n()) %>%
  #converting all columns between and including Menthol and Other to one column called Flavor
  pivot_longer(cols = Menthol:Other, names_to = "Flavor", values_to = "Percentage of students") %>%
  filter(!is.na(`Percentage of students`),
         Flavor!="Other") %>%
  group_by(Flavor) %>%
  mutate(affirmative=(Respondents * `Percentage of students`)/100) %>%
  mutate(flavor_mean = sum(affirmative)/sum(Respondents)) %>%
  ungroup() %>%
  mutate(flavor_mean_rank = dense_rank(flavor_mean),
         Flavor = fct_reorder(Flavor, flavor_mean_rank)) %>%
  ggplot(aes(x=year, y=`Percentage of students`, color=Group)) +
  facet_wrap(.~Flavor,ncol=3) +
  geom_line() + 
  geom_point(show.legend = FALSE) + 
  theme_minimal() +
  theme(legend.position = "bottom",
          axis.title.x = element_blank(),
        axis.text.x = element_text(angle = 90)) + 
  labs(title = "Among users of only one type of product, what vaping flavors appear to be used the most frequently?",
       subtitle = "Percent reporting only e-cigarette use vs only other nicotine product use")

plot5

Question 4

Have vaping rates possibly influenced tobacco/nicotine use?

plot7 <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
    group_by(year) %>%
    summarise(ecig_ever_year=(sum(ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(ecig_ever)),
              ecig_current_year=(sum(ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(ecig_current)),
              non_ecig_ever_year=(sum(non_ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_ever)),
              non_ecig_current_year=(sum(non_ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_current))) %>%
    pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    mutate(User = case_when(Category =="ecig_ever_year" ~ "Ever",
                           Category =="non_ecig_ever_year" ~ "Ever",
                           Category =="ecig_current_year" ~ "Current",
                           Category =="non_ecig_current_year" ~ "Current")) %>%
    mutate(Product = case_when(Category =="ecig_ever_year" ~ "E-cigarettes",
                           Category =="non_ecig_ever_year" ~ "Other products",
                           Category =="ecig_current_year" ~ "E-cigarettes",
                           Category =="non_ecig_current_year" ~ "Other products")) %>%
    filter(User=="Ever") %>%
    ggplot(aes(x=year,y=`Percentage of students`, color=Product)) +
    geom_line(linetype=1) + # geom_bar(stat="identity", position = "dodge", color="black") +
  geom_point(show.legend = FALSE) +
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "bottom",
          axis.title.x = element_blank()) +
    labs(title = "How does e-cigarette ever use compare to ever use of other products over the years?",
         subtitle = "E-cigarette and non-e-cigarette use",
         y = "% of students")

plot7

plot8 <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
    group_by(year) %>%
    summarise(ecig_ever_year=(sum(ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(ecig_ever)),
              ecig_current_year=(sum(ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(ecig_current)),
              non_ecig_ever_year=(sum(non_ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_ever)),
              non_ecig_current_year=(sum(non_ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_current))) %>%
    pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(User = case_when(Category =="ecig_ever_year" ~ "Ever",
                           Category =="non_ecig_ever_year" ~ "Ever",
                           Category =="ecig_current_year" ~ "Current",
                           Category =="non_ecig_current_year" ~ "Current")) %>%
    mutate(Product = case_when(Category =="ecig_ever_year" ~ "E-cigarettes",
                           Category =="non_ecig_ever_year" ~ "Other products",
                           Category =="ecig_current_year" ~ "E-cigarettes",
                           Category =="non_ecig_current_year" ~ "Other products")) %>%
    ggplot(aes(x=year,y=`Percentage of students`, color=Product, linetype=User)) +
    geom_line() +
  geom_point(show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "bottom",
          axis.title.x = element_blank()) +
    labs(title = "How does e-cigarette use compare to use of other products over the years?",
         subtitle = "E-cigarette and non-e-cigarette use",
         y = "% of students")

plot8

Weighted Sample

plotA_w <- nyts_data %>%
    mutate(tobacco_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE),
           tobacco_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(tobacco_ever = case_when(tobacco_sum_ever > 0 ~ TRUE,
                                    tobacco_sum_ever ==0 ~ FALSE),
           tobacco_current = case_when(tobacco_sum_current > 0 ~ TRUE,
                                    tobacco_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
  summarise(tobacco_ever_year = survey_mean(tobacco_ever, vartype = "ci", na.rm=TRUE),
            tobacco_current_year = survey_mean(tobacco_current, vartype = "ci", na.rm=TRUE))  %>%
  mutate_at(vars(-year), "*", 100) %>%
    pivot_longer(cols = -year, names_to = "Type", values_to = "Percentage of students") %>%
    # gather(key=Type,
    #        value=`Percentage of students`,
    #        -year) %>%
  mutate(Estimate = case_when(grepl("_low", Type) ~ "Lower",
                          grepl("_upp", Type) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Type) ~ "Ever",
                          grepl("current", Type) ~ "Current",
                          TRUE ~ "Mean")) %>%
  dplyr::select(-Type) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  ggplot(aes(x=year,y=Mean)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
    scale_y_continuous(breaks = seq(0,70,by=10),
                       labels = seq(0,70,by=10),
                       limits = c(0,70)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "Nicotine product users more prevalent after 2017",
         y = "% of students")

plotB_w <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
    summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year)  %>%
  mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("current", Category) ~ "Current",
                          TRUE ~ "Ever",),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  filter(User=="Ever") %>%
  dplyr::rename("Lower_temp" = Upper,
                "Upper_temp" = Lower) %>%
  dplyr::rename("Lower"=Lower_temp,
                "Upper"=Upper_temp) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(linetype=1) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% ever trying e-cigarettes increases &\n% ever trying other products decreases",
         y = "% of students")

#### the wrangling looks the same as the above plot...
plotC_w <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
  summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Category) ~ "Ever",
                          grepl("current", Category) ~ "Current"),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% Using e-cigarettes increases &\n% using Other products decreases",
         y = "% of students")

title_w <- ggdraw() + 
  draw_label(
    expression("Have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=14,
    x = 0,
    hjust = 0
  ) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_w <- plot_grid(plotA_w,
                     rel_widths = c(1),
                     align = "v",
                     axis = "bt")
plotsBC_w <- plot_grid(plotB_w,
                     plotC_w,
                     rel_widths = c(1,1),
                     align = "v",
                     axis = "bt")

legend_w <- get_legend(plotB_w +
                       theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

figure_w <- plot_grid(title_w,
                      plotsA_w,
                      plotsBC_w,
                      legend_w,
                      ncol = 1,
                      rel_heights = c(0.1,
                                      1,
                                      1,
                                      0.1),
                      scale = 1.0)

figure_w

Hypothethical Cohort

plotA_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(tobacco_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE),
           tobacco_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(tobacco_ever = case_when(tobacco_sum_ever > 0 ~ TRUE,
                                    tobacco_sum_ever ==0 ~ FALSE),
           tobacco_current = case_when(tobacco_sum_current > 0 ~ TRUE,
                                    tobacco_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
  summarise(tobacco_ever_year = survey_mean(tobacco_ever, vartype = "ci", na.rm=TRUE),
            tobacco_current_year = survey_mean(tobacco_current, vartype = "ci", na.rm=TRUE))  %>%
  mutate_at(vars(-year), "*", 100) %>%
    pivot_longer(cols = -year, names_to = "Type", values_to = "Percentage of students")%>%
    # gather(key=Type,
    #        value=`Percentage of students`,
    #        -year) %>%
  mutate(Estimate = case_when(grepl("_low", Type) ~ "Lower",
                          grepl("_upp", Type) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Type) ~ "Ever",
                          grepl("current", Type) ~ "Current",
                          TRUE ~ "Mean")) %>%
  dplyr::select(-Type) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  ggplot(aes(x=year,y=Mean)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_linetype_manual(values = c(2,1)) +
    scale_y_continuous(breaks = seq(0,70,by=10),
                       labels = seq(0,70,by=10),
                       limits = c(0,70)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "Nicotine product users becoming increasingly prevalent",
         y = "% of students")

plotB_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
    summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
   pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students")%>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year)  %>%
  mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("current", Category) ~ "Current",
                          TRUE ~ "Ever",),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  filter(User=="Ever") %>%
  dplyr::rename("Lower_temp" = Upper,
                "Upper_temp" = Lower) %>%
  dplyr::rename("Lower"=Lower_temp,
                "Upper"=Upper_temp) %>%
  ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(linetype=1) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% ever trying nicotine products increases",
         y = "% of students")

plotC_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
  summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students")%>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Category) ~ "Ever",
                          grepl("current", Category) ~ "Current"),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "E-cigarette use surpasses use of other nicotine products",
         y = "% of students")

title_w_8 <- ggdraw() + 
  draw_label(
    expression("Among"~8^th~"graders in 2015, have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=14,
    x = 0,
    hjust = 0
  ) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_w_8 <- plot_grid(plotA_w_8,
                        rel_widths = c(1),
                        align = "v",
                        axis = "bt")

plotsBC_w_8 <- plot_grid(plotB_w_8,
                         plotC_w_8,
                         rel_widths = c(1,1),
                         axis = "bt")

legend_w_8 <- get_legend(plotB_w_8 +
                       theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

figure_w_8 <- plot_grid(title_w_8,
                        plotsA_w_8,
                        plotsBC_w_8,
                        legend_w_8,
                        ncol = 1,
                        rel_heights = c(0.1,
                                      1,
                                      1,
                                      0.1),
                        scale = 1.0
)

figure_w_8

Final Figure

title_final <- ggdraw() +
  draw_label(
    expression("Have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=16,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_uw_final <- ggdraw() + 
  draw_label(
    expression(~6^th~"-"~12^th~"graders, unweighted"),
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_w_final <- ggdraw() + 
  draw_label(
    expression(~6^th~"-"~12^th~"graders, weighted"),
    fontface = 'bold',
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_w_8_final <- ggdraw() + 
  draw_label(
    expression(~8^th~"graders in 2015, weighted"),
    fontface = 'bold',
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_final <- plot_grid(subtitle_uw_final,
                            subtitle_w_final,
                            subtitle_w_8_final,
                            ncol = 3)

plotsA_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of e-cigarette use by user type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_final <- plot_grid(plotA_uw + theme(plot.title = element_blank()),
                          plotA_w + theme(plot.title = element_blank()),
                          plotA_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

plotsB_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of ever use by product type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsB_final <- plot_grid(plotB_uw + theme(plot.title = element_blank()),
                          plotB_w + theme(plot.title = element_blank()),
                          plotB_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

plotsC_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of nicotine product use by product & user type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsC_final <- plot_grid(plotC_uw + theme(plot.title = element_blank()),
                          plotC_w + theme(plot.title = element_blank()),
                          plotC_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

legend_final <- get_legend(plotB_w +
                             theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

final_plot <- plot_grid(title_final,
          plotsA_title_final,
          subtitle_final,
          plotsA_final,
          plotsB_title_final,
          subtitle_final,
          plotsB_final,
          plotsC_title_final,
          subtitle_final,
          plotsC_final,
          legend_final,
          ncol = 1,
          rel_heights = c(0.2,
                          0.2,
                          0.1,
                          1,
                          0.2,
                          0.1,
                          1,
                          0.2,
                          0.1,
                          1,
                          0.1))

final_plot

Suggested Homework


  • Apply survey weights to one of the figures produced in this case study in which weighted estimates were not produced. Include error bars in the updated figure.
    • Does the figure change after the application of survey weights?
    • If so, describe how.
  • Reproduce final_plot above for a different cohort of your choice.

Notes

Ever and current variables are limited to those shared by all years of data included in this case study.

New code: Knit time: 36.308 secs. Previous code: ~ 3 m.

Problems

I had difficulty producing a plot that succinctly presented a trend. It’s very easy to produce plots that are very useful once one is familiar with the data. Some plots, however, cannot stand alone and need additional context to be clear for those without prior knowledge of the data. When I first shared a plot I had been working on with others, it became clear that in my effort to present a complicated idea briefly I had left out information that would make the trend easily interpretable. To solve this issue, I began to present visualizations of the data alongside my original plot. The final figure I created contained several additional plots, each presenting the same trend at a different level than my initial plot.

My “centerpiece” plot is the middle plot in final_plot. The 8 plots around it help provide a very clear picture of what is going on in the US with regards to e-cigarette use and nicotine product use at large. On its own, it’s difficult to understand the trends in the US and how important the weighting scheme is for inference. Once you add the left and right columns, it’s clear what is going on.

Data Analysis


content header


Summary


Session info


R version 4.0.1 (2020-06-06)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Mojave 10.14.5

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] cowplot_1.0.0      ggplot2_3.3.1      srvyr_0.3.10       summarytools_0.9.6
 [5] readr_1.3.1        forcats_0.5.0      tidyr_1.1.0        stringr_1.4.0     
 [9] dplyr_1.0.0        purrr_0.3.4        readxl_1.3.1       knitr_1.28        
[13] here_0.1          

loaded via a namespace (and not attached):
 [1] tidyselect_1.1.0   xfun_0.14          repr_1.1.0         pander_0.6.3      
 [5] mitools_2.4        splines_4.0.1      lattice_0.20-41    tcltk_4.0.1       
 [9] colorspace_1.4-1   vctrs_0.3.0        generics_0.0.2     htmltools_0.4.0   
[13] yaml_2.2.1         base64enc_0.1-3    utf8_1.1.4         survival_3.1-12   
[17] rlang_0.4.6        pillar_1.4.4       glue_1.4.1         withr_2.2.0       
[21] DBI_1.1.0          pryr_0.1.4         matrixStats_0.56.0 lifecycle_0.2.0   
[25] plyr_1.8.6         munsell_0.5.0      gtable_0.3.0       cellranger_1.1.0  
[29] codetools_0.2-16   evaluate_0.14      labeling_0.3       fansi_0.4.1       
[33] highr_0.8          Rcpp_1.0.4.6       backports_1.1.7    scales_1.1.1      
[37] checkmate_2.0.0    jsonlite_1.6.1     magick_2.3         farver_2.0.3      
[41] rapportools_1.0    hms_0.5.3          digest_0.6.25      stringi_1.4.6     
[45] survey_4.0         rprojroot_1.3-2    grid_4.0.1         cli_2.0.2         
[49] tools_4.0.1        magrittr_1.5       tibble_3.0.1       crayon_1.3.4      
[53] pkgconfig_2.0.3    ellipsis_0.3.1     Matrix_1.2-18      skimr_2.1.1       
[57] lubridate_1.7.8    assertthat_0.2.1   rmarkdown_2.2      R6_2.4.1          
[61] compiler_4.0.1    
LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBWYXBpbmcgQmVoYXZpb3JzIGluIEFtZXJpY2FuIFlvdXRoIgphdXRob3I6ICJNaWNoYWVsIE9udGl2ZXJvcywgQ2FycmllIFdyaWdodCwgUGhELiAiCgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0X3RpbWVfc3RhcnQgPC0gU3lzLnRpbWUoKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTgsIGRwaT0zMDApIApgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGtuaXRyKQpgYGAKCgojIyMjIHsub3V0bGluZSB9CmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4MDAgcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiZmluYWxfcGxvdC5wbmciKSkKYGBgCiMjIyMKCgoKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgKipNb3RpdmF0aW9uKioKKioqIApBY2NvcmRpbmcgdG8gYSByZWNlbnQgW3JlcG9ydF0oaHR0cHM6Ly93d3cuY2RjLmdvdi9tbXdyL3ZvbHVtZXMvNjgvd3IvbW02ODA2ZTEuaHRtP3NfY2lkPW1tNjgwNmUxX3cpe3RhcmdldD0iX2JsYW5rIn0sIG92ZXJhbGwgdG9iYWNjbyB1c2UgKippbmNyZWFzZWQqKiBpbiB5b3V0aHMgKG1pZGRsZSBzY2hvb2xhbmQgaGlnaCBzY2hvb2wgc3R1ZGVudHMpIGluIHRoZSBVbml0ZWQgU3RhdGVzIGluIDIwMTcgYW5kIDIwMTgsIGRlc3BpdGUgcHJldmlvdXMgeWVhcnMgb2YgZGVjbGluaW5nIHVzZS4KClRoaXMgbWFqb3IgaW5jcmVhc2UgaXMgYXR0cmlidXRlZCB0byBhbiBpbmNyZWFzZSBpbiB0aGUgdXNlIG9mIGVsZWN0cm9uaWMgY2lnYWFyZXR0ZSAoZS1jaWdhcmV0dGUpIHByb2R1Y3RzLgoKRS1jaWdhcmV0dGVzIGFyZSByZWZlcnJlZCB0byBieSBtYW55IGRpZmZlcmVudCBuYW1lcywgaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0bzoKCjEpIEVsZWN0cm9uaWMgbmljb3RpbmUgZGVsaXZlcnkgc3lzdGVtcyAoRU5EUykKMikgVmFwZXMKMykgZS1ob29rYWhzCjQpIHZhcGUgcGVucwo1KSB0YW5rcwo2KSBtb2RzCgpUaGUgZGV2aWNlcyB2YXJ5IGdyZWF0bHk6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQoKaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cubHVuZy5vcmcvZ2V0bWVkaWEvOGFjOGFiOGMtZTdmYy00OTdiLTgzODQtNDQxNjE1ZjUwZmYwL2VjaWdzX0suanBnLmpwZyIpCmBgYAoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3Lmx1bmcub3JnL3F1aXQtc21va2luZy9lLWNpZ2FyZXR0ZXMtdmFwaW5nL2x1bmctaGVhbHRoKV0KClNlZSB0aGlzIFtDREMgZ3VpZGVdKGh0dHBzOi8vd3d3LmNkYy5nb3YvdG9iYWNjby9iYXNpY19pbmZvcm1hdGlvbi9lLWNpZ2FyZXR0ZXMvcGRmcy9lY2lnYXJldHRlLW9yLXZhcGluZy1wcm9kdWN0cy12aXN1YWwtZGljdGlvbmFyeS01MDgucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCB0aGUgW0FtZXJpY2FuIEx1bmcgQXNzb2NpYXRpb24gd2Vic2l0ZV0oaHR0cHM6Ly93d3cubHVuZy5vcmcvcXVpdC1zbW9raW5nL2UtY2lnYXJldHRlcy12YXBpbmcvbHVuZy1oZWFsdGgpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24uIAoKVGhlIHJlcG9ydCBmb3VuZCB0aGF0OgoKPiBEdXJpbmcgMjAxN+KAkzIwMTgsIGN1cnJlbnQgdXNlIG9mIGFueSB0b2JhY2NvIHByb2R1Y3QgKippbmNyZWFzZWQgMzguMyUqKiAoZnJvbSAxOS42JSB0byAyNy4xJSkgYW1vbmcgaGlnaCBzY2hvb2wgc3R1ZGVudHMgYW5kICoqMjguNiUqKiAoZnJvbSA1LjYlIHRvIDcuMiUpIGFtb25nIG1pZGRsZSBzY2hvb2wgc3R1ZGVudHM7IGUtY2lnYXJldHRlIHVzZSAqKmluY3JlYXNlZCA3Ny44JSoqIChmcm9tIDExLjclIHRvIDIwLjglKSBhbW9uZyBoaWdoIHNjaG9vbCBzdHVkZW50cyBhbmQgKio0OC41JSoqIChmcm9tIDMuMyUgdG8gNC45JSkgYW1vbmcgbWlkZGxlIHNjaG9vbCBzdHVkZW50cy4KCgpJbiAyMDE4LCB0aGUgW0ZlZGVyYWwgRHJ1ZyBBZG1pbmlzdHJhdGlvbiAoRkRBKSBpbiB0aGUgVW5pdGVkIFN0YXRlc10oaHR0cHM6Ly9hY3Nqb3VybmFscy5vbmxpbmVsaWJyYXJ5LndpbGV5LmNvbS9kb2kvZnVsbC8xMC4xMDAyL2NuY3IuMzE4Njgpe3RhcmdldD0iX2JsYW5rIn0gc3RhdGVkIHRoYXQgZS1jaWdhcmV0dGUgdXNhZ2UgdXNlIGFtb25nIHlvdXRoIHJlYWNoZWQ6ICAKCj4g4oCcbm90aGluZyBzaG9ydCBvZiBhbiAqKmVwaWRlbWljIHByb3BvcnRpb24gb2YgZ3Jvd3RoKirigJ0KCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgYmUgaW52aXN0aWdhdGluZyB0aGUgc2FtZSBkYXRhIHVzZWQgaW4gdGhlIHJlcG9ydCB0aGF0IGdlbmVyYXRlZCB0aGUgYWJvdmUgZmluZGluZ3MuIFRoaXMgZGF0YSBjb21lcyBmcm9tIHRoZSBbVGhlIE5hdGlvbmFsIFlvdXRoIFRvYmFjY28gU3VydmV5IChOWVRTKV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2RhdGFfc3RhdGlzdGljcy9zdXJ2ZXlzL255dHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LgoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KCkdlbnR6a2UsIEFuZHJlYSBTLiwgTWVsaXNhIENyZWFtZXIsIEthcmVuIEEuIEN1bGxlbiwgQnJpZGdldCBLLiBBbWJyb3NlLCBHb3Jkb24gV2lsbGlzLCBBaG1lZCBKYW1hbCwgYW5kIEJyaWFuIEEuIEtpbmcuICDigJxWaXRhbCBTaWduczogVG9iYWNjbyBQcm9kdWN0IFVzZSBBbW9uZyBNaWRkbGUgYW5kIEhpZ2ggU2Nob29sIFN0dWRlbnRzIC0gVW5pdGVkIFN0YXRlcywgMjAxMS0yMDE4LuKAnSAqKk1NV1IuIE1vcmJpZGl0eSBhbmQgTW9ydGFsaXR5IFdlZWtseSBSZXBvcnQqKiA2OCAoNik6IDE1N+KAkzY0ICgyMDE5KS4KCiMjIyMKCgojIyAqKk1haW4gUXVlc3Rpb25zKioKKioqIAoKIyMjIyB7Lm1haW5fcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBPdXIgbWFpbiBxdWVzdGlvbjogPC91PjwvYj4KCjEpIEhvdyBoYXMgdG9iYWNjby9uaWNvdGluZSB1c2UgYnkgQW1lcmljYW4geW91dGhzIGNoYW5nZWQgc2luY2UgMjAxNT8gCjIpIEhvdyBkbyB2YXBpbmcgcmF0ZXMgY29tcGFyZSBiZXR3ZWVuIG1hbGVzIGFuZCBmZW1hbGVzPwozKSBXaGF0IHZhcGluZyBicmFuZHMgYW5kIGZsYXZvcnMgYXBwZWFyIHRvIGJlIHVzZWQgdGhlIG1vc3QgZnJlcXVlbnRseT8gIApXZSB3aWxsIGJhc2UgdGhpcyBvbiB0aGUgZm9sbG93aW5nIHN1cnZleSBxdWVzdGlvbnM6ICAgCj4gIkR1cmluZyB0aGUgcGFzdCAzMCBkYXlzLCB3aGF0IGJyYW5kIG9mIGUtY2lnYXJldHRlcyBkaWQgeW91IHVzdWFsbHkgdXNlPyIgICAKPiJXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0CjMwIGRheXM/IiAgCgo0KSBIYXZlIHZhcGluZyByYXRlcyBwb3NzaWJseSBpbmZsdWVuY2VkIHRvYmFjY28vbmljb3RpbmUgdXNlPwoKIyMjIwoKCiMjICoqTGVhcm5pbmcgT2JqZWN0aXZlcyoqIAoqKiogCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgY292ZXIgaG93IHRvIGltcG9ydCBkYXRhIGZyb20gbXVsdGlwbGUgZmlsZXMgZWZmaWNpZW50bHksIGhvdyB0byBpbXBvcnQgZGF0YSBmcm9tIGV4Y2VsIGZpbGVzLCBhbmQgaG93IHRvIG1ha2UgYSB2YXJpZXR5IG9mIHZpc3VhbGl6YXRpb25zIHRvIGNvbXBhcmUgbXVsdGlwbGUgZ3JvdXBzIGFjcm9zcyB0aW1lLiBXZSB3aWxsIGFsc28gZGVtb25zdHJhdGUgaG93IHRvIHdvcmsgd2l0aCBjb2RlYm9va3MuIFdlIHdpbGwgY292ZXIgdGhlIGNvbmNlcHQgb2Ygc3VydmV5IHdlaWdodGluZyBhbmQgaW50cm9kdWNlIHRoZSBgc3J2eXJgIHBhY2thZ2UuIFdlIHdpbGwgZGlzY3VzcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHBvb2xlZCBjcm9zcy1zZWN0aW9uYWwgZGF0YSBhbmQgcGFuZWwgZGF0YS4gV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3Igd3JhbmdsaW5nIGRhdGEsIHN1Y2ggYXMgYHRpZHlyYCBhbmQgYGRweXJgIGFuZCBmb3IgdmlzdWFsaXphdGlvbiwgc3VjaCBhcyBhcyBgZ2dwbG90MmAuIFRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gV2hpbGUgc29tZSBzdHVkZW50cyBtYXkgYmUgZmFtaWxpYXIgd2l0aCBwcmV2aW91cyBSIHByb2dyYW1taW5nIHBhY2thZ2VzLCB0aGVzZSBwYWNrYWdlcyBtYWtlIGRhdGEgc2NpZW5jZSBpbiBSIGVzcGVjaWFsbHkgZWZmaWNpZW50LgoKCmBgYHtyLCBvdXQud2lkdGggPSAiMjAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQoKaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKCioqKiAKCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0aWR5cikKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHN1bW1hcnl0b29scykKbGlicmFyeShzcnZ5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGNvd3Bsb3QpCmBgYAoKIFBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YSAgCltyZWFkeGxdKGh0dHBzOi8vcmVhZHhsLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBpbXBvcnQgdGhlIGRhdGEgaW4gdGhlIGV4Y2VsIGZpbGVzICAKW3B1cnJyXShodHRwczovL3B1cnJyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBpbXBvcnQgdGhlIGRhdGEgaW4gYWxsIHRoZSBkaWZmZXJlbnQgZXhjZWwgYW5kIGNzdiBmaWxlcyBlZmZpY2llbnRseQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCB0aGUgQ1NWIGZpbGUgZGF0YQpbZHBseXJdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGFycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgdGhlIGRhdGEgIApbc3VtbWFyeXRvb2xzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgaW4gYSBkaWZmZXJlbnQgc3R5bGUgICAKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byByZWFycmFuZ2UgZGF0YSBpbiB3aWRlIGFuZCBsb25nIGZvcm1hdHMgCgoKW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnL2FydGljbGVzL3N0cmluZ3IuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1hbmlwdWxhdGUgdGhlIGNoYXJhY3RlciBzdHJpbmdzIHdpdGhpbiB0aGUgZGF0YSAgIApbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFrZSB2aXN1YWxpemF0aW9ucyB3aXRoIG11bHRpcGxlIGxheWVycyAgCltnZ3B1YnJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ3B1YnIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIGVhc2lseSBhZGQgcmVncmVzc2lvbiBsaW5lIGVxdWF0aW9ucyB0byBwbG90cyAgCltmb3JjYXRzXShodHRwczovL2ZvcmNhdHMudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBjaGFuZ2UgZGV0YWlscyBhYm91dCBmYWN0b3JzIChjYXRlZ29yaWNhbCB2YXJpYWJsZXMpICAKW2xtZXJUZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbG1lclRlc3QvbG1lclRlc3QucGRmKXwgdG8gcGVyZm9ybSBsaW5lYXIgbWl4ZWQgbW9kZWwgdGVzdGluZyAgIApbY2FyXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY2FyL2Nhci5wZGYpfCB0byBwZXJmb3JtIExldmVuZSdzIFRlc3Qgb2YgSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2VzICAgCltnZ2lyYXBoXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dpcmFwaC9pbmRleC5odG1sKXwgdG8gbWFrZSBwbG90cyBpbnRlcmFjdGl2ZSAgIApbZ2dmb3JjZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dnZm9yY2UvZ2dmb3JjZS5wZGYpfCB0byBtb2RpZnkgZmFjZXRzIGluIHBsb3RzICAKW3ZpcmlkaXNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXJpZGlzL3ZpZ25ldHRlcy9pbnRyby10by12aXJpZGlzLmh0bWwpfCB0byBwbG90IGluIGNvbG9yIHBhbGV0dGUgICAgCltjb3dwbG90XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY293cGxvdC92aWduZXR0ZXMvaW50cm9kdWN0aW9uLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBhbGxvdyBwbG90cyB0byBiZSBjb21iaW5lZCAgIFtza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhICAgCgoKCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCgojIyAqKkNvbnRleHQqKgoqKiogCgpBY2NvcmRpbmcgdG8gdGhlIGNpdGVkIFtNb3JiaWRpdHkgYW5kIE1vcnRhbGl0eSBXZWVrbHkgUmVwb3J0XShodHRwczovL3d3dy5jZGMuZ292L21td3Ivdm9sdW1lcy82OC93ci9tbTY4MDZlMS5odG0/c19jaWQ9bW02ODA2ZTFfdykgdGhpcyB3YXMgd2hhdCB3YXMgYWxyZWFkeSBrbm93biBhYm91dCB0aGlzIHRvcGljIGFuZCB0aGUgaW1wbGljYXRpb25zIG9mIHRoaXMgc3R1ZHk6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiODAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJjb250ZXh0LnBuZyIpKQoKYGBgCgoKSW1wb3J0YW50bHksIHRoZSB2YXBvcnMgdXNlZCBpbiBlLWNpZ2FyZXR0ZXMgY29udGFpbiBoYXJtZnVsIGNoZW1pY2FsczoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CgppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5jZGMuZ292L3RvYmFjY28vYmFzaWNfaW5mb3JtYXRpb24vZS1jaWdhcmV0dGVzL2ltYWdlcy9lLWNpZ2FyZXR0ZS1hZXJvc29sLWNhbi1jb250YWluLWhhcm1mdWwtaW5ncmVkaWVudHMtZGVza3RvcC03MDAuanBnIikKYGBgCgpFLWNpZ2FyZXR0ZSB1c2FnZSBoYXMgYWxzbyBiZWVuIGFzc29jaWF0ZWQgd2l0aCBbbHVuZyBpbmp1cnldKChodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcGhhci4yMDE5LjAxNjE5L2Z1bGwpKXt0YXJnZXQ9Il9ibGFuayJ9CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiODAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJsdW5nLnBuZyIpKQpgYGAKClNlZSBbaGVyZV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2Jhc2ljX2luZm9ybWF0aW9uL2UtY2lnYXJldHRlcy9RdWljay1GYWN0cy1vbi10aGUtUmlza3Mtb2YtRS1jaWdhcmV0dGVzLWZvci1LaWRzLVRlZW5zLWFuZC1Zb3VuZy1BZHVsdHMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgYWRkaXRvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBwb3RlbnRpYWwgaGVhbHRoIGVmZmVjdHMgb2YgZS1jaWdhcmV0dGVzIGluIHRlZW5zIGFuZCB5b3VuZyBhZHVsdHMuCgojIyAqKkxpbWl0YXRpb25zKioKKioqIApUaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgY29uc2lkZXJhdGlvbnMgcmVnYXJkaW5nIHRoaXMgZGF0YSBhbmFseXNpcyB0byBrZWVwIGluIG1pbmQ6IAoKQVZPQ0FETy4uTmVlZCBNaWNoYWVsIHRvIGxvb2sgYXQgdGhlc2UuLi4KCjEpIFRoZSBkYXRhIGluY2x1ZGVkIGluIHRoZSBbTmF0aW9uYWwgWW91dGggVG9iYWNjbyBTdXJ2ZXkgKE5ZVFMpXShodHRwczovL3d3dy5jZGMuZ292L3RvYmFjY28vZGF0YV9zdGF0aXN0aWNzL3N1cnZleXMvbnl0cy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gZG9lcyBub3QgZm9sbG93IHRoZSBzYW1lIGluZGl2aWR1YWwgc3R1ZGVudHMgb3ZlciB0aW1lLiAgQSBbbG9uZ2l0dWRpbmFsIHN0dWR5XShodHRwczovL3d3dy5ibWouY29tL2Fib3V0LWJtai9yZXNvdXJjZXMtcmVhZGVycy9wdWJsaWNhdGlvbnMvZXBpZGVtaW9sb2d5LXVuaW5pdGlhdGVkLzctbG9uZ2l0dWRpbmFsLXN0dWRpZXMpe3RhcmdldD0iX2JsYW5rIn0gdGhhdCBkb2VzIGZvbGxvdyB0aGUgc2FtZSBpbmRpdmlkdWFscyBvdmVyIHRpbWUgY29sbGVjdHMgZGF0YSBjYWxsZWQgW3BhbmVsIGRhdGFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhbmVsX2RhdGEpLiBUaGUgZGF0YSBpbiB0aGlzIHN0dWR5IGlzIGNhbGxlZCBwb29sZWQgW2Nyb3NzLXNlY3Rpb25hbCBkYXRhXWh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXNlY3Rpb25hbF9kYXRhLCB0aGlzIGRhdGEgaXMgb2J0YWluZWQgZnJvbSByYW5kb20gY29sbGVjdGlvbiBvZiBvYmVydmF0aW9ucyBhY3Jvc3MgdGltZS4KCkFjY29yZGluZyB0byB3aWtpcGVkaWE6Cj5QYW5lbCBkYXRhIGRpZmZlcnMgZnJvbSBwb29sZWQgY3Jvc3Mtc2VjdGlvbmFsIGRhdGEgYWNyb3NzIHRpbWUsIGJlY2F1c2UgaXQgZGVhbHMgd2l0aCB0aGUgb2JzZXJ2YXRpb25zIG9uIHRoZSBzYW1lIHN1YmplY3RzIGluIGRpZmZlcmVudCB0aW1lcyB3aGVyZWFzIHRoZSBsYXR0ZXIgb2JzZXJ2ZXMgZGlmZmVyZW50IHN1YmplY3RzIGluIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMKCgpBVk9DQURPIHJldmlzaXQgdGhpcy4uLgoyKSBUaGUgZGF0YSBhbHNvIGluY2x1ZGVzIHBlcmNlbnRhZ2VzIG9mIHN0dWRlbnRzIHRoYXQgcmVwb3J0ZWQgdXNlIG9mIHBhcnRpY3VsYXIgdG9iYWNjbyBwcm9kdWN0LCBidXQgdGhlIHN1cnZleSBxdWVzdGlvbnMgZGlkIG5vdCBhc2sgIGhvdyBtdWNoIHVzZXMgb2Ygb25lIHByb2R1Y3QgY29tcGFyZWQgdG8gYW5vdGhlciAtIGZvciBleGFtcGxlIG1lbnRob2wgZmxhdm9yZWQgcHJvZHVjdHMgd2hlcmUgdXNlZCBhdCB0aGUgbmVhciBleGNsdXNpb24gb2Ygb3RoZXIgZmxhdm9ycy4gCgpXaGlsZSBbZ2VuZGVyXShodHRwczovL3d3dy5nZW5kZXJzcGVjdHJ1bS5vcmcvcXVpY2stbGlua3MvdW5kZXJzdGFuZGluZy1nZW5kZXIvKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCBbc2V4XShodHRwczovL3d3dy53aG8uaW50L2dlbm9taWNzL2dlbmRlci9lbi9pbmRleDEuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBhcmUgbm90IGFjdHVhbGx5IGJpbmFyeSwgdGhlIGRhdGEgIHVzZWQgaW4gdGhpcyBhbmFseXNpcyBvbmx5IGNvbnRhaW5zIGluZm9ybWF0aW9uIGZvciBncm91cHMgb2YgaW5kaXZpZHVhbHMgd2hvIGFuc3dlcmVkIHRoZSBzdXJ2ZXkgcXVlc3Rpb25zIGFzIG1hbGUgb3IgZmVtYWxlLiAKCgpBVk9DQURPLi4gc2hvdWxkIHdlIGRyb3AgdGhlIHJhY2UgZGF0YT8gd2UgZGlkbnQgdXNlIGl0Li4uCkZ1cnRoZXJtb3JlLCB3aGlsZSB0aGUgcmFjZSBvZiBpbmRpdmlkdWFsIHN0dWRlbnRzIHdhcyBzdXJ2ZXllZCBhbmQgYXNrZWQgc3R1ZGVudHMgdG8gc2VsZiByZXBvcnQgYmFzZWQgb24gd2hhdCByYWNlIG9yIHJhY2VzIHRoZXkgY29uc2lkZXJlZCB0aGVtc2VsdmVzIHRvIGJlLCB0aGlzIGxpc3Qgb25seSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIG9wdGlvbnM6ICAgIAoxKSBIaXNwYW5pYywgTGF0aW5vLCBMYXRpbmEsIG9yIFNwYW5pc2ggb3JpZ2luIGFzIG9uZSBzaW5nbGUgcmFjZSB3aXRoIHRoZSBmb2xsb3dpbmcgZnVydGhlciBvcHRpb25zOiAgCiAgICAxKSBNZXhpY2FuLCBNZXhpY2FuIEFtZXJpY2FuLCBDaGljYW5vLCBvciBDaGljYW5hICAKICAgIDIpIFB1ZXJ0byBSaWNhbiAgCiAgICAzKSBDdWJhbiAgCiAgICA0KSBZZXMsIEFub3RoZXIgSGlzcGFuaWMsIExhdGlubywgTGF0aW5hLCBvciBTcGFuaXNoIG9yaWdpbiAgCjIpCgoKIyMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKgoqKiogCiAKVGhlIGRhdGEgaW4gdGhpcyBjYXNlIHN0dWR5IGNvbWVzIGZyb20gdGhlIFtOYXRpb25hbCBZb3V0aCBUb2JhY2NvIFN1cnZleSAoTllUUyldKGh0dHBzOi8vd3d3LmNkYy5nb3YvdG9iYWNjby9kYXRhX3N0YXRpc3RpY3Mvc3VydmV5cy9ueXRzL2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSB3aGljaCBpcyBhbiBhbm51YWwgc3VydmV5IHRoYXQgYXNrcyBzdHVkZW50cyAgaW4gaGlnaCBzY2hvb2wgYW5kIG1pZGRsZSBzY2hvb2wgKGdyYWRlcyA2LTEyKSBhYm91dCB0b2JhY2NvIHVzYWdlIGluIHRoZSBVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EuCgpUaGUgZGF0YSBmb3IgdGhpcyBzdXJ2ZXkgaXMgZnJlZWx5IGF2YWlsYWJsZSBvbmxpbmUgYXQgdGhpcyBbd2Vic2l0ZV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2RhdGFfc3RhdGlzdGljcy9zdXJ2ZXlzL255dHMvZGF0YS9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHdpdGggZGF0YSBmcm9tIDE5OTksIDIwMDAsIDIwMDIsIDIwMDQsIDIwMDYsIDIwMDksICBhbmQgMjAxMS0yMDE5LiBXZSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJvbSAqKjIwMTUtMjAxOSoqIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZXNlIHllYXJzIGFyZSB0aGUgbW9zdCByZWNlbnQgdGhhdCBhc2tlZCBxdWVzdGlvbnMgcmVjYXJkaW5nIGUtY2lnYXJldHRlIHVzYWdlLgoKRWFjaCB5ZWFyIGluY2x1ZGVzIGRvY3VtZW50YXRpb24sIHN1Y2ggYXMgYSBbY29kZWJvb2tdKGh0dHBzOi8vd3d3LmljcHNyLnVtaWNoLmVkdS9pY3BzcndlYi9jb250ZW50L3NoYXJlZC9JQ1BTUi9mYXFzL3doYXQtaXMtYS1jb2RlYm9vay5odG1sKSBhbmQgYW4gZXhjZWwgZmlsZSBjb250YWluaW5nIHRoZSBkYXRhOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIiwgb3V0LndpZHRoID0gIjYwMCBweCJ9Cgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiZGF0YS5wbmciKSkKYGBgClRoZXJlZm9yZSwgc2luY2Ugd2UgYXJlIHVzaW5nIGRhdGEgZnJvbSAqKjIwMTUtMjAxOSoqLCB0aGUgZGF0YSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBpcyBsb2NhdGVkIGluIDUgZGlmZmVyZW50IGV4Y2VsIGZpbGVzLCBlYWNoIHdpdGggdGhlaXIgb3duIFtjb2RlYm9va10oaHR0cHM6Ly93d3cuaWNwc3IudW1pY2guZWR1L2ljcHNyd2ViL2NvbnRlbnQvc2hhcmVkL0lDUFNSL2ZhcXMvd2hhdC1pcy1hLWNvZGVib29rLmh0bWwpLgoKVGhlIFtjb2RlYm9va10oaHR0cHM6Ly93d3cuaWNwc3IudW1pY2guZWR1L2ljcHNyd2ViL2NvbnRlbnQvc2hhcmVkL0lDUFNSL2ZhcXMvd2hhdC1pcy1hLWNvZGVib29rLmh0bWwpIGNvbnRhaW5zIGluZm9ybWF0aW9uIGRlc2NyaWJpbmcgdGhlIGRhdGEgd2l0aGluIHRoZSBleGNlbCBmaWxlLiAKCkFzIHlvdSBjYW4gc2VlIHRoZSBleGNlbCBmaWxlIGNvbnRhaW5zIHZlcnkgc2hvcnQgdmFyaWFibGUgbmFtZXMgYW5kIHZhbHVlcywgYW5kIGl0IGlzIG5vdCBjbGVhciB3aGF0IHRoZXkgbWVhbiB3aXRob3V0IHRoZSBjb2RlYm9vazoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciIsIG91dC53aWR0aCA9ICI2MDAgcHgifQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImV4Y2VsLnBuZyIpKQpgYGAKClRoZSBjb2RlYm9vayBleHBsYWlucyB3aGF0IHRoZSB2YXJpYWJsZXMgKHRoZSBjb2x1bW5zKSBhcmU6CmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciIsIG91dC53aWR0aCA9ICI2MDAgcHgifQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInZhcmlhYmxlcy5wbmciKSkKYGBgCgpBbmQgdGhlIGNvZGVib29rIGV4cGxhaW5zIHdoYXQgdGhlIHZhbHVlcyBmb3IgZWFjaCB2YXJpYWJsZSBhcmU6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiNjAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJxbjEucG5nIikpCmBgYAoKV2Ugd2lsbCBleHBsYWluIG1vcmUgbGF0ZXIgYWJvdXQgd2hhdCB0aGUgdmFsdWVzIG9uIHRoZSByaWdodCBpbmRpY2F0ZS4KClRoZSByZWFzb24gdGhhdCB0aGVyZSBhcmUgY29kZWJvb2tzIGZvciBlYWNoIHllYXIgaXMgYmVjYXVzZSB0aGUgcXVlc3Rpb25zIGFza2VkIHllYXIgdmFyaWVkIHNsaWdodGx5LgoKClRoZSBkYXRhIGluIHRoaXMgc3VydmV5IGlzIHdoYXQgaXMgY2FsbGVkIHBvb2xlZCBjcm9zcy1zZWN0aW9uYWwgZGF0YS4gSW4gb3RoZXJ3b3JkcywgZGlmZmVyZW50IHN1YnNldHMgb2Ygc3R1ZGVudHMgYXJlIHN1cnZleWVkIGVhY2ggeWVhciBhbmQgaXQgaXMgbm90IGNsZWFyIHdoaWNoLCBpZiBhbnkgLCBpbmRpdmlkdWFscyBwYXJ0aWNwYXRlIGZyb20gb25lIHllYXIgdG8gdGhlIG5leHQuCgojIyAqKkRhdGEgSW1wb3J0KioKKioqIAoKIyMjIFJlYWRpbmcgaW4gdGhlIGV4Y2VsIGZpbGVzCioqKgpTaW5jZSB0aGVzZSBleGNlbCBmaWxlcyBhcmUgc28gbGFyZ2UsIGl0IHRha2VzIGEgYml0IG9mIHRpbWUgZm9yIHRoZSBkYXRhIHRvIGxvYWQuIFRvIG1ha2UgdGhlIHByb2Nlc3MgZmFzdGVyLCB3ZSBwcmV2aW91c2x5IGltcG9ydGVkIHRoZXNlIGZpbGVzLCBzZWxlY3RlZCBvbmx5IG91ciBxdWVzdGlvbnMgb2YgaW50ZXJlc3QsIGFuZCBzYXZlZCB0aGlzIGRhdGEgYXMgY3N2IGZpbGVzLiAKCkFWT0NBRE8gc2hvdWxkIHdlIGRyb3AgdGhlIHJhY2UgZGF0YT8gd2UgZGlkbid0IGVuZCB1cCBkb2luZyBhbnl0aGluZyB3aXRoIHRoaXMuLi4uCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSBmb3IgZGV0YWlscyBvbiBob3cgdGhlIGRhdGEgd2FzIG9yaWdpbmFsbHkgaW1wb3J0ZWQgPC9zdW1tYXJ5PgoKRmlyc3Qgd2UgY3JlYXRlZCBhIGxpc3Qgb2YgZmlsZW5hbWVzIG9mIGFsbCB0aGUgZGlmZmVyZW50IGV4Y2VsIGZpbGVzLiBVc2luZyB0aGUgYGhlcmUoKWAgZnVuY3Rpb24gb2YgdGhlIGBoZXJlYCBwYWNrYWdlLCB3ZSBsb29rZWQgaW4gYWxsIHRoZSBkaXJlY3RvcmllcyBvZiB0aGUgcHJvamVjdC4KVGhlIGBsaXN0LmZpbGVzKClgIGZ1bmN0aW9uIGxvb2tlZCBmb3IgYWxsIGZpbGVzIHdpdGggLnhsc3ggd2l0aGluIHRoZXNlIHN1YmRpcmVjdG9yaWVzLgpgYGB7cn0KZXhjZWxfZmlsZXM8LWxpc3QuZmlsZXMoaGVyZTo6aGVyZSgpLCByZWN1cnNpdmUgPSBUUlVFLAogICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIioueGxzeCIpCmV4Y2VsX2ZpbGVzCmBgYAoKQWxsIHRoZSBmaWxlcyB3ZXJlIHJlYWQgdXNpbmcgcmVhZF9leGNlbCBvZiB0aGUgcmVhZHhsIHBhY2thZ2UuVXNpbmcgdGhlIGBtYXAoKWAgZnVuY3Rpb24gb2YgdGhlIGBwdXJycmAgcGFja2FnZSB0aGlzIHdhcyBkb25lIGVmZmljaWVudGx5LgpUaGlzIGNyZWF0ZWQgYSBzaW5nbGUgbGlzdCBvZiB0aWJibGVzIChvbmUgZm9yIGVhY2ggZmlsZSkuIApgYGB7ciwgZXZhbCA9IEZBTFNFfQp0YmwgPC0gZXhjZWxfZmlsZXMgJT4lIAogICAgICAgbWFwKH5yZWFkeGw6OnJlYWRfZXhjZWwoLikpCmBgYAoKRWFjaCBleGNlbCBmaWxlIG5hbWUgd2FzIGV4dHJhY3RlZCB1c2luZyB0aGUgYHN0cl9leHRyYWN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZS4KYGBge3J9CnRibF9uYW1lcyA8LSBleGNlbF9maWxlcyAlPiUKICBzdHJfZXh0cmFjdCgibnl0c1syXVswXVsxXVs1LTldIikKdGJsX25hbWVzCmBgYAoKVGhlc2UgbmFtZXMgYmVjYW1lIHRoZSBuYW1lcyBvZiB0aGUgdGliYmxlcyBpbiB0aGUgbGlzdCBvZiB0aWJibGVzLgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpuYW1lcyh0YmwpIDwtIHRibF9uYW1lcwpgYGAKCgpTcGVjaWZpYyBjb2x1bW5zIHdlcmUgc2VsZWN0ZWQgZnJvbSBlYWNoIG9mIHRoZSB0aWJibGVzIHVzaW5nIHRoZSB2YXJhaWJsZSBuYW1lLCBhcyBpZGVudGlmaWVkIGluIHRoZSBjb2RlYm9vayBmb3IgYmVpbmcgb2YgaW50ZXJlc3QuCkluIHNvbWUgY2FzZXMgZnVuY3Rpb25zIGxpa2UgYHN0YXJ0c193aXRoKClgIG9mIHRoZSBgZHBseXJgIHBhY2thZ2Ugd2VyZSB1c2VkIHRvIHNlbGVjdCBzZXZlcmFsIHZhcmlhYmxlcy4KCmBgYHtyLCBldmFsID0gRkFMU0V9Cgp0YmxbWyJueXRzMjAxNSJdXSA8LSB0YmxbWyJueXRzMjAxNSJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFFuMSwgI0FnZQogICAgICAgICAgICAgICAgICBRbjIsICNTZXgKICAgICAgICAgICAgICAgICAgUW4zLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlFuNCIpLCAjSGlzcGFuaWMvTGF0aW5vCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRbjUiKSwgI1JhY2UsCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIEVGTEFWQ0lHVFMsCiAgICAgICAgICAgICAgICAgIENGTEFWQ0lHVFMsCiAgICAgICAgICAgICAgICAgIEVGTEFWQ0lHQVIsCiAgICAgICAgICAgICAgICAgICkKCnRibFtbIm55dHMyMDE2Il1dIDwtIHRibFtbIm55dHMyMDE2Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsCiAgICAgICAgICAgICAgICAgIGZpbndndCwKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICAgICAgICAgICAgICAgUTEsICNBZ2UKICAgICAgICAgICAgICAgICAgUTIsICNTZXgKICAgICAgICAgICAgICAgICAgUTMsICNHcmFkZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTQiKSwgI0hpc3BhbmljL0xhdGlubwogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTUiKSwgI1JhY2UKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgRUZMQVZDSUdBUiwKICAgICAgICAgICAgICAgICAgUTUwQSwgI01lbnRob2wgIyBXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0IDMwIGRheXM/IChTZWxlY3Qgb25lIG9yIG1vcmUpCiAgICAgICAgICAgICAgICAgIFE1MEIsICNDbG92ZSBvciBzcGljZQogICAgICAgICAgICAgICAgICBRNTBDLCAjRnJ1aXQKICAgICAgICAgICAgICAgICAgUTUwRCwgI0Nob2NvbGF0ZQogICAgICAgICAgICAgICAgICBRNTBFLCAjQWxjb2hvbGljIERyaW5rCiAgICAgICAgICAgICAgICAgIFE1MEYsICNDYW5keS9EZXNzZXJ0cy9PdGhlciBTd2VldHMKICAgICAgICAgICAgICAgICAgUTUwRywgI1NvbWUgT3RoZXIgRmxhdm9yIE5vdCBMaXN0ZWQgSGVyZQogICAgICAgICAgICAgICAgICBRNTBIICNJIERpZCBOb3QgVXNlIEZsYXZvcmVkIFRvYmFjY28gUHJvZHVjdHMgSW4gdGhlIFBhc3QKICAgICAgICAgICAgICAgICAgKSAKCnRibFtbIm55dHMyMDE3Il1dIDwtIHRibFtbIm55dHMyMDE3Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsCiAgICAgICAgICAgICAgICAgIGZpbndndCwKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICAgICAgICAgICAgICAgUTEsICNBZ2UKICAgICAgICAgICAgICAgICAgUTIsICNTZXgKICAgICAgICAgICAgICAgICAgUTMsICNHcmFkZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTQiKSwgI0hpc3BhbmljL0xhdGlubwogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTUiKSwgI1JhY2UKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgQ0JJRElTLAogICAgICAgICAgICAgICAgICBRNTBBLCAjTWVudGhvbCAjIFdoYXQgZmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIGhhdmUgeW91IHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cz8gKFNlbGVjdCBvbmUgb3IgbW9yZSkKICAgICAgICAgICAgICAgICAgUTUwQiwgI0Nsb3ZlIG9yIHNwaWNlCiAgICAgICAgICAgICAgICAgIFE1MEMsICNGcnVpdAogICAgICAgICAgICAgICAgICBRNTBELCAjQ2hvY29sYXRlCiAgICAgICAgICAgICAgICAgIFE1MEUsICNBbGNvaG9saWMgRHJpbmsKICAgICAgICAgICAgICAgICAgUTUwRiwgI0NhbmR5L0Rlc3NlcnRzL090aGVyIFN3ZWV0cwogICAgICAgICAgICAgICAgICBRNTBHLCAjU29tZSBPdGhlciBGbGF2b3IgTm90IExpc3RlZCBIZXJlCiAgICAgICAgICAgICAgICAgIFE1MEggI0kgRGlkIE5vdCBVc2UgRmxhdm9yZWQgVG9iYWNjbyBQcm9kdWN0cyBJbiB0aGUgUGFzdAogICAgICAgICAgICAgICAgICApCgp0YmxbWyJueXRzMjAxOCJdXSA8LSB0YmxbWyJueXRzMjAxOCJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFExLCAjQWdlCiAgICAgICAgICAgICAgICAgIFEyLCAjU2V4CiAgICAgICAgICAgICAgICAgIFEzLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE0IiksICNIaXNwYW5pYy9MYXRpbm8KICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE1IiksICNSYWNlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIFE1MEEsICNNZW50aG9sICMgV2hhdCBmbGF2b3JzIG9mIHRvYmFjY28gcHJvZHVjdHMgaGF2ZSB5b3UgdXNlZCBpbiB0aGUgcGFzdCAzMCBkYXlzPyAoU2VsZWN0IG9uZSBvciBtb3JlKQogICAgICAgICAgICAgICAgICBRNTBCLCAjQ2xvdmUgb3Igc3BpY2UKICAgICAgICAgICAgICAgICAgUTUwQywgI0ZydWl0CiAgICAgICAgICAgICAgICAgIFE1MEQsICNDaG9jb2xhdGUKICAgICAgICAgICAgICAgICAgUTUwRSwgI0FsY29ob2xpYyBEcmluawogICAgICAgICAgICAgICAgICBRNTBGLCAjQ2FuZHkvRGVzc2VydHMvT3RoZXIgU3dlZXRzCiAgICAgICAgICAgICAgICAgIFE1MEcsICNTb21lIE90aGVyIEZsYXZvciBOb3QgTGlzdGVkIEhlcmUKICAgICAgICAgICAgICAgICAgUTUwSCAjSSBEaWQgTm90IFVzZSBGbGF2b3JlZCBUb2JhY2NvIFByb2R1Y3RzIEluIHRoZSBQYXN0CiAgICAgICAgICAgICAgICAgICkKCnRibFtbIm55dHMyMDE5Il1dIDwtIHRibFtbIm55dHMyMDE5Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsCiAgICAgICAgICAgICAgICAgIGZpbndndCwKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICAgICAgICAgICAgICAgUTEsICNBZ2UKICAgICAgICAgICAgICAgICAgUTIsICNTZXgKICAgICAgICAgICAgICAgICAgUTMsICNHcmFkZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTQiKSwgI0hpc3BhbmljL0xhdGlubwogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTUiKSwgI1JhY2UKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgRUhUUCwKICAgICAgICAgICAgICAgICAgQ0hUUCwKICAgICAgICAgICAgICAgICAgUTQwLCAjQnJhbmcsIGUtY2lnYXJldHRlcwogICAgICAgICAgICAgICAgICBRNjJBLCAjTWVudGhvbCAjIFdoYXQgZmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIGhhdmUgeW91IHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cz8gKFNlbGVjdCBvbmUgb3IgbW9yZSkKICAgICAgICAgICAgICAgICAgUTYyQiwgI0Nsb3ZlIG9yIHNwaWNlCiAgICAgICAgICAgICAgICAgIFE2MkMsICNGcnVpdCAKICAgICAgICAgICAgICAgICAgUTYyRCwgI0Nob2NvbGF0ZQogICAgICAgICAgICAgICAgICBRNjJFLCAjQWxjb2hvbGljIERyaW5rCiAgICAgICAgICAgICAgICAgIFE2MkYsICNDYW5keS9EZXNzZXJ0cy9PdGhlciBTd2VldHMKICAgICAgICAgICAgICAgICAgUTYyRywgI1NvbWUgT3RoZXIgRmxhdm9yIE5vdCBMaXN0ZWQgSGVyZSAKICAgICAgICAgICAgICAgICAgKQpgYGAKCkEgZGlyZWN0b3J5IHdhcyBjcmVhdGVkIHVzaW5nIHRoZSBiYXNlIGBkaXIuY3JlYXRlKClgIGZ1bmN0aW9uIGNhbGxlZCBgZGF0YV9yZWR1Y2VkYCBmb3IgdGhlIGNzdiBmaWxlcy4gCk5ldyBjc3YgZmlsZXMgd2VyZSBjcmVhdGVkIGZvciBlYWNoIG9mIHRoZSB0YmxzIGluIHRoZSBsaXN0IHVzaW5nIHRoZSBgd3JpdGVfY3N2KClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVhZHJgIHBhY2thZ2UuClRoaXMgd2FzIGRvbmUgYWxsIGF0IG9uY2UgdXNpbmcgdGhlIGJhc2UgYG1hcHB5KClgIGZ1bmN0aW9uLgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KIyAKZGlyLmNyZWF0ZSgiZG9jcy9kYXRhX3JlZHVjZWQiKQoKbWFwcGx5KHdyaXRlX2NzdiwgdGJsLCBwYXRoPWhlcmUocGFzdGUwKCJkb2NzL2RhdGFfcmVkdWNlZC8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXModGJsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLmNzdicpKQogICAgICkKIyB0YmwgJT4lCiMgICBuYW1lcyguKSAlPiUKIyBtYXAofndyaXRlX2Nzdih0aWJibGUoLikgLCBwYXRoPXBhc3RlMCgiZG9jcy9kYXRhX3JlZHVjZWQyLyIsLiwgIi5jc3YiKSkpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIApgYGAKCjwvZGV0YWlscz4KCgoKTm93IHdlIHdpbGwgc2hvdyBob3cgdG8gcmVhZCBpbiB0aGUgZGF0YSBmcm9tIHRoZSBmaXZlIGNzdiBmaWxlcyB0aGF0IHdlcmUgY3JlYXRlZCBmcm9tIHRoZSBmaXZlIGRpZmZlcmVudCBleGNlbCBmaWxlcy4KCiMjIyBSZWFkaW5nIGluIHRoZSBDU1YgZmlsZXMKKioqCgpgYGB7ciwgZWNobz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpCgplbmRfdGltZSA8LSBTeXMudGltZSgpCgp0ZXN0X3RpbWUgPC0gZW5kX3RpbWUgLSBzdGFydF90aW1lCgp0aW1lX21lc3NhZ2UgPC0gcGFzdGUoIkR1cmF0aW9uIG9mIGRhdGEgaW1wb3J0OiIsCiAgICAgIHJvdW5kKGFzLm51bWVyaWModGVzdF90aW1lKSAsMyksCiAgICAgIHVuaXRzKHRlc3RfdGltZSkKICAgICAgKQpgYGAKCgpgYGB7cn0KY3N2cyA8LSBsaXN0LmZpbGVzKGhlcmU6OmhlcmUoKSxyZWN1cnNpdmUgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIqLmNzdiIpJT4lCiAgbWFwKH5yZWFkX2NzdiguKSkKCgpjc3ZzX25hbWVzIDwtIGxpc3QuZmlsZXMocmVjdXJzaXZlID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiKi5jc3YiKSU+JQogIHN0cl9leHRyYWN0KCJueXRzWzJdWzBdWzFdWzUtOV0iKQoKbmFtZXMoY3N2cykgPC0gY3N2c19uYW1lcwoKbnl0c19kYXRhIDwtIGNzdnMKcm0oY3N2cykKcm0oY3N2c19uYW1lcykKYGBgCgoKIyMgKipEYXRhIEV4cGxvcmF0aW9uIGFuZCBXcmFuZ2xpbmcqKgoqKiogCgoKIyMjIFJlbmFtaW5nIHZhcmlhYmxlcyAgCioqKiAKCkhlcmUgaXMgd2hhdCB0aGUgZGF0YSBmb3IgMjAxNSBsb29rcyBsaWtlOgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyfQpnbGltcHNlKG55dHNfZGF0YVtbIm55dHMyMDE1Il1dKQpgYGAKIyMjIwoKQ3VycmVudGx5LCBpdCBpc24ndCB2ZXJ5IGNsZWFyIHdoYXQgbW9zdCBvZiB0aGUgdmFyaWFibGVzIGluZGljYXRlLgoKV2Ugd2FudCB0byByZW5hbWUgdmFyaWFibGVzIGxpa2UgYFFuMWAgdG8gc29tZXRoaW5nIG1vcmUgbWVhbmluZ2Z1bCBsaWtlIGBBZ2VgLgoKVG8gZG8gdGhpcyB3ZSB3aWxsIHVzZSB0aGUgYHJlbmFtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBZb3UgY291bGQgYWxzbyB1c2UgZnVuY3Rpb25zIGluIHRoZSBgdGlkeXNlbGVjdGAgcGFja2FnZQpgYGB7cn0KCm55dHNfZGF0YVtbIm55dHMyMDE1Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE1Il1dICU+JQogICAgZHBseXI6OnJlbmFtZShBZ2U9UW4xLAogICAgICAgICAgIGZlbWFsZT1RbjIsCiAgICAgICAgICAgR3JhZGU9UW4zLAogICAgICAgICAgIE5vdF9ITD1RbjRhLAogICAgICAgICAgIEhMX01leD1RbjRiLAogICAgICAgICAgIEhMX1BSPVFuNGMsCiAgICAgICAgICAgSExfQ3ViPVFuNGQsCiAgICAgICAgICAgSExfT3RoZXI9UW40ZSwKICAgICAgICAgICBSYWNlX0FJQU49UW41YSwKICAgICAgICAgICBSYWNlX0FzaWFuPVFuNWIsCiAgICAgICAgICAgUmFjZV9CQUE9UW41YywKICAgICAgICAgICBSYWNlX05IT1BJPVFuNWQsCiAgICAgICAgICAgUmFjZV9XaGl0ZT1RbjVlKSAlPiUKICAgIG11dGF0ZShBZ2U9QWdlKzgsCiAgICAgICAgICAgR3JhZGU9R3JhZGUrNSwKICAgICAgICAgICBicmFuZF9lY2lnPU5BLAogICAgICAgICAgIG1lbnRob2w9TkEsCiAgICAgICAgICAgY2xvdmVfc3BpY2U9TkEsCiAgICAgICAgICAgZnJ1aXQ9TkEsCiAgICAgICAgICAgY2hvY29sYXRlPU5BLAogICAgICAgICAgIGFsY29ob2xpY19kcmluaz1OQSwKICAgICAgICAgICBjYW5keV9kZXNzZXJ0X3N3ZWV0cz1OQSwKICAgICAgICAgICBvdGhlcj1OQSwKICAgICAgICAgICBub191c2U9TkEpICU+JQogIGRwbHlyOjpzZWxlY3QoLXN0YXJ0c193aXRoKCJRIikpCmBgYAoKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CmdsaW1wc2Uobnl0c19kYXRhW1sibnl0czIwMTUiXV0pCnNraW1yOjpza2ltKG55dHNfZGF0YVtbIm55dHMyMDE1Il1dKQpgYGAKIyMjIwoKCmBgYHtyfQojTm90ZSBhYm91dCBkaWZmZXJlbmNlIGJldHdlZW4gcmVjb2RlIGFuZCBmY3RfcmVjb2RlCm55dHNfZGF0YVtbIm55dHMyMDE1Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE1Il1dICU+JQogIG11dGF0ZV9hbGwofiByZXBsYWNlKC4sIC4gJWluJSBjKCIuIiksIE5BKSkgJT4lCiAgbXV0YXRlKEFnZT1hcy5jaGFyYWN0ZXIoQWdlKSwKICAgICAgICAgR3JhZGU9YXMuY2hhcmFjdGVyKEdyYWRlKQogICAgICAgICApICU+JQogIG11dGF0ZShBZ2U9cmVjb2RlKEFnZSwKICAgICAgICAgICAgICAgICAgICBgMTlgID0gIj4xOCIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgZmVtYWxlPXJlY29kZShmZW1hbGUsCiAgICAgICAgICAgICAgICAgICAgICBgMWA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgYDJgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IE5BKSwKICAgICAgICAgR3JhZGU9cmVjb2RlKEdyYWRlLAogICAgICAgICAgICAgICAgICAgICAgYDEzYCA9ICJVbmdyYWRlZC9PdGhlciIpLAogICAgICAgICBOb3RfSEw9cmVjb2RlKE5vdF9ITCwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkhMIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIlJhY2UiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAyYCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBOQSkpKQpgYGAKCgpgYGB7cn0Kbnl0c19kYXRhW1sibnl0czIwMTYiXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTYiXV0gJT4lCiAgICByZW5hbWUoQWdlPVExLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBHcmFkZT1RMywKICAgICAgICAgICBOb3RfSEw9UTRBLAogICAgICAgICAgIEhMX01leD1RNEIsCiAgICAgICAgICAgSExfUFI9UTRDLAogICAgICAgICAgIEhMX0N1Yj1RNEQsCiAgICAgICAgICAgSExfT3RoZXI9UTRFLAogICAgICAgICAgIFJhY2VfQUlBTj1RNUEsCiAgICAgICAgICAgUmFjZV9Bc2lhbj1RNUIsCiAgICAgICAgICAgUmFjZV9CQUE9UTVDLAogICAgICAgICAgIFJhY2VfTkhPUEk9UTVELAogICAgICAgICAgIFJhY2VfV2hpdGU9UTVFLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBtZW50aG9sPVE1MEEsCiAgICAgICAgICAgY2xvdmVfc3BpY2U9UTUwQiwKICAgICAgICAgICBmcnVpdD1RNTBDLAogICAgICAgICAgIGNob2NvbGF0ZT1RNTBELAogICAgICAgICAgIGFsY29ob2xpY19kcmluaz1RNTBFLAogICAgICAgICAgIGNhbmR5X2Rlc3NlcnRfc3dlZXRzPVE1MEYsCiAgICAgICAgICAgb3RoZXI9UTUwRywKICAgICAgICAgICBub191c2U9UTUwSCkgJT4lCiAgICBtdXRhdGUoQWdlID0gYXMubnVtZXJpYyhBZ2UpICsgOCwKICAgICAgICAgICBHcmFkZSA9IGFzLm51bWVyaWMoR3JhZGUpICsgNSwKICAgICAgICAgICBicmFuZF9lY2lnPU5BKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1zdGFydHNfd2l0aCgiUSIpKQpgYGAKCgpgYGB7cn0Kbnl0c19kYXRhW1sibnl0czIwMTYiXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTYiXV0gJT4lCiAgbXV0YXRlX2FsbCh+IHJlcGxhY2UoLiwgLiAlaW4lIGMoIioiLCAiKioiKSwgTkEpKSAlPiUKICBtdXRhdGUoQWdlPWFzLmNoYXJhY3RlcihBZ2UpLAogICAgICAgICBHcmFkZT1hcy5jaGFyYWN0ZXIoR3JhZGUpCiAgICAgICAgICkgJT4lCiAgbXV0YXRlKEFnZT1yZWNvZGUoQWdlLAogICAgICAgICAgICAgICAgICAgIGAxOWAgPSAiPjE4IiwKICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBmZW1hbGU9cmVjb2RlKGZlbWFsZSwKICAgICAgICAgICAgICAgICAgICAgIGAxYD0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBgMmAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gTkEpLAogICAgICAgICBHcmFkZT1yZWNvZGUoR3JhZGUsCiAgICAgICAgICAgICAgICAgICAgICBgMTNgID0gIlVuZ3JhZGVkL090aGVyIiksCiAgICAgICAgIE5vdF9ITD1yZWNvZGUoTm90X0hMLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiSEwiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiUmFjZSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpICU+JQogICAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgMmAgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICAgIG11dGF0ZV9hdCh2YXJzKG1lbnRob2w6bm9fdXNlKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKQoKYGBgCgpgYGB7cn0Kbnl0c19kYXRhW1sibnl0czIwMTciXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTciXV0gJT4lCiAgICByZW5hbWUoQWdlPVExLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBHcmFkZT1RMywKICAgICAgICAgICBOb3RfSEw9UTRBLAogICAgICAgICAgIEhMX01leD1RNEIsCiAgICAgICAgICAgSExfUFI9UTRDLAogICAgICAgICAgIEhMX0N1Yj1RNEQsCiAgICAgICAgICAgSExfT3RoZXI9UTRFLAogICAgICAgICAgIFJhY2VfQUlBTj1RNUEsCiAgICAgICAgICAgUmFjZV9Bc2lhbj1RNUIsCiAgICAgICAgICAgUmFjZV9CQUE9UTVDLAogICAgICAgICAgIFJhY2VfTkhPUEk9UTVELAogICAgICAgICAgIFJhY2VfV2hpdGU9UTVFLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBtZW50aG9sPVE1MEEsCiAgICAgICAgICAgY2xvdmVfc3BpY2U9UTUwQiwKICAgICAgICAgICBmcnVpdD1RNTBDLAogICAgICAgICAgIGNob2NvbGF0ZT1RNTBELAogICAgICAgICAgIGFsY29ob2xpY19kcmluaz1RNTBFLAogICAgICAgICAgIGNhbmR5X2Rlc3NlcnRfc3dlZXRzPVE1MEYsCiAgICAgICAgICAgb3RoZXI9UTUwRywKICAgICAgICAgICBub191c2U9UTUwSCkgJT4lCiAgICBtdXRhdGUoQWdlID0gYXMubnVtZXJpYyhBZ2UpICsgOCwKICAgICAgICAgICBHcmFkZSA9IGFzLm51bWVyaWMoR3JhZGUpICsgNSwKICAgICAgICAgICBicmFuZF9lY2lnPU5BKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1zdGFydHNfd2l0aCgiUSIpKQpgYGAKCmBgYHtyfQpueXRzX2RhdGFbWyJueXRzMjAxNyJdXSA8LSBueXRzX2RhdGFbWyJueXRzMjAxNyJdXSAlPiUKICBtdXRhdGVfYWxsKH4gcmVwbGFjZSguLCAuICVpbiUgYygiKiIsICIqKiIpLCBOQSkpICU+JQogIG11dGF0ZShBZ2U9YXMuY2hhcmFjdGVyKEFnZSksCiAgICAgICAgIEdyYWRlPWFzLmNoYXJhY3RlcihHcmFkZSkKICAgICAgICAgKSAlPiUKICBtdXRhdGUoQWdlPXJlY29kZShBZ2UsCiAgICAgICAgICAgICAgICAgICAgYDE5YCA9ICI+MTgiLAogICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIGZlbWFsZT1yZWNvZGUoZmVtYWxlLAogICAgICAgICAgICAgICAgICAgICAgYDFgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGAyYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBOQSksCiAgICAgICAgIEdyYWRlPXJlY29kZShHcmFkZSwKICAgICAgICAgICAgICAgICAgICAgIGAxM2AgPSAiVW5ncmFkZWQvT3RoZXIiKSwKICAgICAgICAgTm90X0hMPXJlY29kZShOb3RfSEwsCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJITCIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJSYWNlIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAyYCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpICU+JQogICAgbXV0YXRlX2F0KHZhcnMobWVudGhvbDpub191c2UpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpCmBgYAoKYGBge3J9Cm55dHNfZGF0YVtbIm55dHMyMDE4Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE4Il1dICU+JQogICAgcmVuYW1lKEFnZT1RMSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgR3JhZGU9UTMsCiAgICAgICAgICAgTm90X0hMPVE0QSwKICAgICAgICAgICBITF9NZXg9UTRCLAogICAgICAgICAgIEhMX1BSPVE0QywKICAgICAgICAgICBITF9DdWI9UTRELAogICAgICAgICAgIEhMX090aGVyPVE0RSwKICAgICAgICAgICBSYWNlX0FJQU49UTVBLAogICAgICAgICAgIFJhY2VfQXNpYW49UTVCLAogICAgICAgICAgIFJhY2VfQkFBPVE1QywKICAgICAgICAgICBSYWNlX05IT1BJPVE1RCwKICAgICAgICAgICBSYWNlX1doaXRlPVE1RSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgbWVudGhvbD1RNTBBLAogICAgICAgICAgIGNsb3ZlX3NwaWNlPVE1MEIsCiAgICAgICAgICAgZnJ1aXQ9UTUwQywKICAgICAgICAgICBjaG9jb2xhdGU9UTUwRCwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9UTUwRSwKICAgICAgICAgICBjYW5keV9kZXNzZXJ0X3N3ZWV0cz1RNTBGLAogICAgICAgICAgIG90aGVyPVE1MEcsCiAgICAgICAgICAgbm9fdXNlPVE1MEgpICU+JQogICAgbXV0YXRlKEFnZSA9IGFzLm51bWVyaWMoQWdlKSArIDgsCiAgICAgICAgICAgR3JhZGUgPSBhcy5udW1lcmljKEdyYWRlKSArIDUsCiAgICAgICAgICAgYnJhbmRfZWNpZz1OQSkgJT4lCiAgZHBseXI6OnNlbGVjdCgtc3RhcnRzX3dpdGgoIlEiKSkKYGBgCgoKYGBge3J9Cm55dHNfZGF0YVtbIm55dHMyMDE4Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE4Il1dICU+JQogIG11dGF0ZV9hbGwofiByZXBsYWNlKC4sIC4gJWluJSBjKCIqIiwgIioqIiksIE5BKSkgJT4lCiAgbXV0YXRlKEFnZT1hcy5jaGFyYWN0ZXIoQWdlKSwKICAgICAgICAgR3JhZGU9YXMuY2hhcmFjdGVyKEdyYWRlKQogICAgICAgICApICU+JQogICAgbXV0YXRlKEFnZT1yZWNvZGUoQWdlLAogICAgICAgICAgICAgICAgICAgIGAxOWAgPSAiPjE4IiwKICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBmZW1hbGU9cmVjb2RlKGZlbWFsZSwKICAgICAgICAgICAgICAgICAgICAgIGAxYD0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBgMmAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gTkEpLAogICAgICAgICBHcmFkZT1yZWNvZGUoR3JhZGUsCiAgICAgICAgICAgICAgICAgICAgICBgMTNgID0gIlVuZ3JhZGVkL090aGVyIiksCiAgICAgICAgIE5vdF9ITD1yZWNvZGUoTm90X0hMLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiSEwiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiUmFjZSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgYDJgID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IE5BKSkpICU+JQogICAgbXV0YXRlX2F0KHZhcnMobWVudGhvbDpub191c2UpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpCmBgYAoKYGBge3J9Cm55dHNfZGF0YVtbIm55dHMyMDE5Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE5Il1dICU+JQogICAgcmVuYW1lKGJyYW5kX2VjaWc9UTQwLAogICAgICAgICAgIEFnZT1RMSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgR3JhZGU9UTMsCiAgICAgICAgICAgTm90X0hMPVE0QSwKICAgICAgICAgICBITF9NZXg9UTRCLAogICAgICAgICAgIEhMX1BSPVE0QywKICAgICAgICAgICBITF9DdWI9UTRELAogICAgICAgICAgIEhMX090aGVyPVE0RSwKICAgICAgICAgICBSYWNlX0FJQU49UTVBLAogICAgICAgICAgIFJhY2VfQXNpYW49UTVCLAogICAgICAgICAgIFJhY2VfQkFBPVE1QywKICAgICAgICAgICBSYWNlX05IT1BJPVE1RCwKICAgICAgICAgICBSYWNlX1doaXRlPVE1RSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgbWVudGhvbD1RNjJBLAogICAgICAgICAgIGNsb3ZlX3NwaWNlPVE2MkIsCiAgICAgICAgICAgZnJ1aXQ9UTYyQywKICAgICAgICAgICBjaG9jb2xhdGU9UTYyRCwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9UTYyRSwKICAgICAgICAgICBjYW5keV9kZXNzZXJ0X3N3ZWV0cz1RNjJGLAogICAgICAgICAgIG90aGVyPVE2MkcpICU+JQogICAgbXV0YXRlKEFnZSA9IGFzLm51bWVyaWMoQWdlKSArIDgsCiAgICAgICAgICAgR3JhZGUgPSBhcy5udW1lcmljKEdyYWRlKSArIDUsCiAgICAgICAgICAgbm9fdXNlPSJtaXNzaW5nIikgJT4lCiAgZHBseXI6OnNlbGVjdCgtc3RhcnRzX3dpdGgoIlEiKSkKYGBgCgoKYGBge3J9Cm55dHNfZGF0YVtbIm55dHMyMDE5Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE5Il1dICU+JQogIG11dGF0ZV9hbGwofiByZXBsYWNlKC4sIC4gJWluJSBjKCIuTiIsIi5TIiwiLloiKSwgTkEpKSAlPiUKICBtdXRhdGUoQWdlPWFzLmNoYXJhY3RlcihBZ2UpLAogICAgICAgICBHcmFkZT1hcy5jaGFyYWN0ZXIoR3JhZGUpCiAgICAgICAgICkgJT4lCiAgbXV0YXRlKHBzdT1hcy5jaGFyYWN0ZXIocHN1KSwKICAgICAgICAgQWdlPXJlY29kZShBZ2UsCiAgICAgICAgICAgICAgICAgICAgYDE5YCA9ICI+MTgiLAogICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIGZlbWFsZT1yZWNvZGUoZmVtYWxlLAogICAgICAgICAgICAgICAgICAgICAgYDFgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGAyYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IE5BKSwKICAgICAgICAgR3JhZGU9cmVjb2RlKEdyYWRlLAogICAgICAgICAgICAgICAgICAgICAgYDEzYCA9ICJVbmdyYWRlZC9PdGhlciIpLAogICAgICAgICBOb3RfSEw9cmVjb2RlKE5vdF9ITCwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkhMIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIlJhY2UiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICAgIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDJgID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gTkEpKSkgJT4lCiAgICBtdXRhdGUoYnJhbmRfZWNpZyA9IHJlY29kZShicmFuZF9lY2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSAiT3RoZXIiLCAjbGV2ZWxzIDEsOCBjb21iaW5lZCB0byBgT3RoZXJgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMmAgPSAiQmx1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYDNgID0gIkpVVUwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgNGAgPSAiTG9naWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgNWAgPSAiTWFya1RlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA2YCA9ICJOSk9ZIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYDdgID0gIlZ1c2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgOGAgPSAiT3RoZXIiKSkgJT4lCiAgICBtdXRhdGVfYXQodmFycyhtZW50aG9sOm5vX3VzZSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID1GQUxTRSkpKSAjQXNrIE1pY2hhZWwgYWJvdXQgdGhpcyBpZiB1bmNsZWFyCgpgYGAKCmBgYHtyfQpueXRzX2RhdGEgPC0gbnl0c19kYXRhICU+JQogIG1hcF9kZihiaW5kX3Jvd3MsIC5pZCA9ICJ5ZWFyIikgJT4lCiAgbXV0YXRlKHllYXI9YXMubnVtZXJpYyhzdHJfcmVtb3ZlKHllYXIsIm55dHMiKSkpCgojc2FwcGx5KG55dHNfZGF0YSwgY2xhc3MpCgojIHNhcHBseShueXRzX2RhdGEsIGZ1bmN0aW9uKHgpCiMgICAgIHN1bW1hcnkoCiMgICAgICAgICBmYWN0b3IoeCkKIyAgICAgICAgICkKIyAgICAgKQoKCmBgYAoKPHN0eWxlPgpkaXYuYmx1ZSB7IGJhY2tncm91bmQtY29sb3I6I2U2ZjBmZjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJibHVlIj4KClJlbWluZGVyOiBDdXJyZW50IHVzZXJzIGFyZSBhIHN1YnNldCBvZiBldmVyIHVzZXJzLiAKCjwvZGl2PgoKCgpXZSB3aWxsIGFsc28gdXNlIHRoZSBgJT4lYCBwaXBlIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGRlZmluZSB0aGUgaW5wdXQgZm9yIGxhdGVyIHNlcXVlbnRpYWwgc3RlcHMuIFRoaXMgd2lsbCBtYWtlIG1vcmUgc2Vuc2Ugd2hlbiB3ZSBoYXZlIG11bHRpcGxlIHNlcXVlbnRpYWwgc3RlcHMgdXNpbmcgdGhlIHNhbWUgZGF0YSBvYmplY3QuIFRvIHVzZSB0aGUgcGlwZSBub3RhdGlvbiB3ZSBuZWVkIHRvIGluc3RhbGwgYW5kIGxvYWQgZHBseXIgYXMgd2VsbC4KCgoKIyMgKipEYXRhIFZpc3VhbGl6YXRpb24qKgoqKiogCgojIyMgUXVlc3Rpb24gMSAKCkZvciBsb3RzIG9mIHBpdm90X2xvbmdlcigpIHRoYXQgYXJlIHRoZSBzYW1lLi4uIGNhbiB1c2UgcGl2b3RfbG9uZ2VyX3NwZWMoKQoKc3BlYyA8LSByZWxpZ19pbmNvbWUgJT4lIGJ1aWxkX2xvbmdlcl9zcGVjKAogIGNvbHMgPSAtcmVsaWdpb24sCiAgbmFtZXNfdG8gPSAiaW5jb21lIiwKICB2YWx1ZXNfdG8gPSAiY291bnQiCikKcGl2b3RfbG9uZ2VyX3NwZWMocmVsaWdfaW5jb21lLCBzcGVjKQoKQnV0IG5lZWQgdG8gZGVjaWRlIGlmIHdlIGFyZSBnb2luZyB0byBjcmVhdGUgc29tZSBuZXcgZGF0YSBmcmFtZXMuLi4KCmBgYHtyfQpwbG90MSA8LSBueXRzX2RhdGEgJT4lCiAgICBtdXRhdGUodG9iYWNjb19zdW1fZXZlciA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICB0b2JhY2NvX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZSh0b2JhY2NvX2V2ZXIgPSBjYXNlX3doZW4odG9iYWNjb19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2JhY2NvX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICB0b2JhY2NvX2N1cnJlbnQgPSBjYXNlX3doZW4odG9iYWNjb19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2JhY2NvX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICAgIHN1bW1hcmlzZSh0b2JhY2NvX2V2ZXJfeWVhcj0oc3VtKHRvYmFjY29fZXZlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYSh0b2JhY2NvX2V2ZXIpKSwKICAgICAgICAgICAgICB0b2JhY2NvX2N1cnJlbnRfeWVhcj0oc3VtKHRvYmFjY29fY3VycmVudCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYSh0b2JhY2NvX2N1cnJlbnQpKSkgJT4lCiAgICByZW5hbWUoIkV2ZXIiPXRvYmFjY29fZXZlcl95ZWFyLAogICAgICAgICAgICJDdXJyZW50Ij10b2JhY2NvX2N1cnJlbnRfeWVhcikgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiVXNlciIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIiklPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBsaW5ldHlwZT1Vc2VyKSkgKwogICAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygyLDEpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsNzAsYnk9MTApLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgwLDcwLGJ5PTEwKSwKICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsNzApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiSG93IGRvZXMgbmljb3RpbmUgdXNlIHZhcnkgb3ZlciB0aGUgeWVhcnM/IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ3VycmVudCBhbmQgZXZlciB1c2VycyBvZiBuaWNvdGluZSBwcm9kdWN0cyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90MSAKYGBgCgojIyMgUXVlc3Rpb24gMgoKYGBge3J9CnBsb3QyIDwtIG55dHNfZGF0YSAlPiUKICAgIGdyb3VwX2J5KHllYXIsCiAgICAgICAgICAgICBmZW1hbGUpICU+JQogICAgc3VtbWFyaXNlKEVFTENJR1RfeWVhcj0oc3VtKEVFTENJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoRUVMQ0lHVCkpLAogICAgICAgICAgICAgIENFTENJR1RfeWVhcj0oc3VtKENFTENJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoQ0VMQ0lHVCkpKSAlPiUgCiAgICBmaWx0ZXIoIWlzLm5hKGZlbWFsZSkpICU+JQogICAgcmVuYW1lKCJFLWNpZ2FyZXR0ZXMsIEV2ZXIiPUVFTENJR1RfeWVhciwKICAgICAgICAgICAiRS1jaWdhcmV0dGVzLCBDdXJyZW50Ij1DRUxDSUdUX3llYXIpICU+JQogICNjb252ZXJ0aW5nIGFsbCBjb2x1bW5zIGJldHdlZW4gYW5kIGluY2x1ZGluZyBgRS1jaWdhcmV0dGVzLCBFdmVyYCBhbmQgYEUtY2lnYXJldHRlcywgQ3VycmVudGAgaW50byBvbmUgY29sdW1uIGNhbGxlZCBjYXRlZ29yeQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBgRS1jaWdhcmV0dGVzLCBFdmVyYDpgRS1jaWdhcmV0dGVzLCBDdXJyZW50YCwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpJT4lCiAgICBtdXRhdGUoVXNlciA9IGNhc2Vfd2hlbihDYXRlZ29yeSA9PSAiRS1jaWdhcmV0dGVzLCBFdmVyIiB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ICJFLWNpZ2FyZXR0ZXMsIEN1cnJlbnQiIH4gIkN1cnJlbnQiKSkgJT4lCiAgICBtdXRhdGUoU2V4ID0gY2FzZV93aGVuKGZlbWFsZSA9PSBUUlVFIH4gIkZlbWFsZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVtYWxlID09IEZBTFNFIH4gIk1hbGVzIikpICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsIGNvbG9yPVNleCwgbGluZXR5cGU9VXNlcikpICsKICAgIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiSG93IGRvIHZhcGluZyByYXRlcyBjb21wYXJlIGJldHdlZW4gbWFsZXMgYW5kIGZlbWFsZXM/IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ3VycmVudCBhbmQgZXZlciB1c2VycyBieSBnZW5kZXIiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdDIKYGBgCgojIyMgUXVlc3Rpb24gMwoKV2hhdCB2YXBpbmcgYnJhbmRzIGFuZCBmbGF2b3JzIGFwcGVhciB0byBiZSB1c2VkIHRoZSBtb3N0IGZyZXF1ZW50bHk/CgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iSHVhbmcgSiwgRHVhbiBaLCBLd29rIEosIGV0IGFsLiBUb2IgQ29udHJvbCAyMDE5OzI4OjE0NuKAkzE1MS4iLCBvdXQud2lkdGggPSAnMTAwJSd9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJIdWFuZ0pfRHVhblpfS3dva0pfZXRfYWxfVG9iYWNjb0NvbnRyb2xfRmlndXJlMS5wbmciKSkKYGBgCgpbUGFwZXJdKGh0dHBzOi8vdG9iYWNjb2NvbnRyb2wuYm1qLmNvbS9jb250ZW50L3RvYmFjY29jb250cm9sLzI4LzIvMTQ2LmZ1bGwucGRmKQoKCmBgYHtyfQpwbG90MyA8LSBueXRzX2RhdGEgJT4lCiAgICBmaWx0ZXIoeWVhcj09MjAxOSkgJT4lCiAgICBncm91cF9ieShicmFuZF9lY2lnKSAlPiUKICAgIGZpbHRlcighaXMubmEoYnJhbmRfZWNpZykpICU+JQogICAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQogICAgbXV0YXRlKHRvdGFsID0gc3VtKG4pLAogICAgICAgICAgIFBlcmNlbnQgPSBuKjEwMC90b3RhbCkgJT4lCiAgICBtdXRhdGUoYnJhbmRfZWNpZyA9IGZjdF9yZW9yZGVyKGJyYW5kX2VjaWcsIGRlc2MoUGVyY2VudCkpKSAlPiUKICAgIGdncGxvdChhZXMoeD1icmFuZF9lY2lnLHk9UGVyY2VudCwgZmlsbD1icmFuZF9lY2lnKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiV2hhdCB2YXBpbmcgYnJhbmRzIGFwcGVhciB0byBiZSB1c2VkIHRoZSBtb3N0IGZyZXF1ZW50bHk/IiwKICAgICAgICAgc3VidGl0bGUgPSAiQnJhbmQgb2YgZS1jaWdhcmV0dGUgbW9zdCBmcmVxdWVudGx5IHVzZWQgaW4gdGhlIGxhc3QgMzAgZGF5cyAoMjAxOSkiLAogICAgICAgICB5ID0gIiUgb2YgZS1jaWdhcmV0dGUgdXNlcnMgcmVzcG9uZGluZyIpCgpwbG90MwpgYGAKCmBgYHtyfQpwbG90NCA8LSBueXRzX2RhdGEgJT4lCiAgZmlsdGVyKHllYXIhPTIwMTUpICU+JQogIGdyb3VwX2J5KHllYXIpICU+JQogIHN1bW1hcmlzZShNZW50aG9sPShzdW0obWVudGhvbCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShtZW50aG9sKSksCiAgICAgICAgICAgICAgYENsb3ZlIG9yIFNwaWNlYD0oc3VtKGNsb3ZlX3NwaWNlLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGNsb3ZlX3NwaWNlKSksCiAgICAgICAgICAgICAgYEZydWl0YD0oc3VtKGZydWl0LCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGZydWl0KSksCiAgICAgICAgICAgICAgYENob2NvbGF0ZWA9KHN1bShjaG9jb2xhdGUsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoY2hvY29sYXRlKSksCiAgICAgICAgICAgICAgYEFsY29ob2xpYyBEcmlua2A9KHN1bShhbGNvaG9saWNfZHJpbmssIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoYWxjb2hvbGljX2RyaW5rKSksCiAgICAgICAgICAgICAgYENhbmR5L0Rlc3NlcnRzL1N3ZWV0c2A9KHN1bShjYW5keV9kZXNzZXJ0X3N3ZWV0cywgbmEucm0gPSBUUlVFKSoxMDApL3N1bSghaXMubmEoY2FuZHlfZGVzc2VydF9zd2VldHMpKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIsIHZhbHVlc190byA9ICJGbGF2b3IiKSAlPiUKCiAgZ2dwbG90KGFlcyh4PXllYXIsIHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1GbGF2b3IpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBsYWJzKHRpdGxlID0gIldoYXQgZmxhdm9ycyBhcHBlYXIgdG8gYmUgdXNlZCB0aGUgbW9zdCBmcmVxdWVudGx5IGluIG5pY290aW5lIHByb2R1Y3RzPyIsCiAgICAgICBzdWJ0aXRsZSA9ICJGbGF2b3JzIG9mIHRvYmFjY28gcHJvZHVjdHMgdXNlZCBpbiB0aGUgcGFzdCAzMCBkYXlzIikKCnBsb3Q0IApgYGAKCmBgYHtyfQpwbG90NSA8LSBueXRzX2RhdGEgJT4lCiAgZmlsdGVyKHllYXIhPTIwMTUpICU+JQogIGZpbHRlcihtZW50aG9sPT1UUlVFfAogICAgICAgICAgIGNsb3ZlX3NwaWNlPT1UUlVFfAogICAgICAgICAgIGZydWl0PT1UUlVFfAogICAgICAgICAgIGNob2NvbGF0ZT09VFJVRXwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9PVRSVUV8CiAgICAgICAgICAgY2FuZHlfZGVzc2VydF9zd2VldHM9PVRSVUV8CiAgICAgICAgICAgb3RoZXI9PVRSVUUpICU+JQogIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgbXV0YXRlKGVjaWdfb25seV9ldmVyID0gY2FzZV93aGVuKGVjaWdfZXZlciA9PSBUUlVFICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19ldmVyID09RkFMU0UgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gRkFMU0UpLAogICAgICAgICAgIGVjaWdfb25seV9jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfY3VycmVudCA9PSBUUlVFICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXIgPT1GQUxTRSB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfb25seV9ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX2V2ZXIgPT0gVFJVRSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19ldmVyID09RkFMU0UgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX29ubHlfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19jdXJyZW50ID09IFRSVUUgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfZXZlciA9PUZBTFNFIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IEZBTFNFKSkgJT4lCiAgbXV0YXRlKEdyb3VwID0gY2FzZV93aGVuKGVjaWdfb25seV9ldmVyPT1UUlVFIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX29ubHlfY3VycmVudD09VFJVRSB+ICJPbmx5IGUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19vbmx5X2V2ZXI9PVRSVUUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19vbmx5X2N1cnJlbnQ9PVRSVUUgfiAiT25seSBvdGhlciBwcm9kdWN0cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiQm90aCIpKSAlPiUKICBmaWx0ZXIoR3JvdXAhPSJCb3RoIikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgR3JvdXApICU+JQogIHN1bW1hcmlzZShgTWVudGhvbGA9KHN1bShtZW50aG9sLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgc3VtKCFpcy5uYShtZW50aG9sKSksCiAgICAgICAgICAgICAgYENsb3ZlIG9yIFNwaWNlYD0oc3VtKGNsb3ZlX3NwaWNlLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgc3VtKCFpcy5uYShjbG92ZV9zcGljZSkpLAogICAgICAgICAgICAgIGBGcnVpdGA9KHN1bShmcnVpdCwgbmEucm0gPSBUUlVFKSoxMDApL3N1bSghaXMubmEoZnJ1aXQpKSwKICAgICAgICAgICAgICBgQ2hvY29sYXRlYD0oc3VtKGNob2NvbGF0ZSwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgIHN1bSghaXMubmEoY2hvY29sYXRlKSksCiAgICAgICAgICAgICAgYEFsY29ob2xpYyBEcmlua2A9KHN1bShhbGNvaG9saWNfZHJpbmssIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICBzdW0oIWlzLm5hKGFsY29ob2xpY19kcmluaykpLAogICAgICAgICAgICAgIGBDYW5keS9EZXNzZXJ0cy9Td2VldHNgPShzdW0oY2FuZHlfZGVzc2VydF9zd2VldHMsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICBzdW0oIWlzLm5hKGNhbmR5X2Rlc3NlcnRfc3dlZXRzKSksCiAgICAgICAgICAgIGBPdGhlcmA9KHN1bShvdGhlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgIHN1bSghaXMubmEob3RoZXIpKSwKICAgICAgICAgICAgUmVzcG9uZGVudHM9bigpKSAlPiUKICAjY29udmVydGluZyBhbGwgY29sdW1ucyBiZXR3ZWVuIGFuZCBpbmNsdWRpbmcgTWVudGhvbCBhbmQgT3RoZXIgdG8gb25lIGNvbHVtbiBjYWxsZWQgRmxhdm9yCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBNZW50aG9sOk90aGVyLCBuYW1lc190byA9ICJGbGF2b3IiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpICU+JQogIGZpbHRlcighaXMubmEoYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSwKICAgICAgICAgRmxhdm9yIT0iT3RoZXIiKSAlPiUKICBncm91cF9ieShGbGF2b3IpICU+JQogIG11dGF0ZShhZmZpcm1hdGl2ZT0oUmVzcG9uZGVudHMgKiBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApLzEwMCkgJT4lCiAgbXV0YXRlKGZsYXZvcl9tZWFuID0gc3VtKGFmZmlybWF0aXZlKS9zdW0oUmVzcG9uZGVudHMpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGZsYXZvcl9tZWFuX3JhbmsgPSBkZW5zZV9yYW5rKGZsYXZvcl9tZWFuKSwKICAgICAgICAgRmxhdm9yID0gZmN0X3Jlb3JkZXIoRmxhdm9yLCBmbGF2b3JfbWVhbl9yYW5rKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIsIHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Hcm91cCkpICsKICBmYWNldF93cmFwKC5+Rmxhdm9yLG5jb2w9MykgKwogIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFKSArIAogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsgCiAgbGFicyh0aXRsZSA9ICJBbW9uZyB1c2VycyBvZiBvbmx5IG9uZSB0eXBlIG9mIHByb2R1Y3QsIHdoYXQgdmFwaW5nIGZsYXZvcnMgYXBwZWFyIHRvIGJlIHVzZWQgdGhlIG1vc3QgZnJlcXVlbnRseT8iLAogICAgICAgc3VidGl0bGUgPSAiUGVyY2VudCByZXBvcnRpbmcgb25seSBlLWNpZ2FyZXR0ZSB1c2UgdnMgb25seSBvdGhlciBuaWNvdGluZSBwcm9kdWN0IHVzZSIpCgpwbG90NQpgYGAKCiMjIyBRdWVzdGlvbiA0CgpIYXZlIHZhcGluZyByYXRlcyBwb3NzaWJseSBpbmZsdWVuY2VkIHRvYmFjY28vbmljb3RpbmUgdXNlPwoKYGBge3J9CnBsb3Q2IDwtIG55dHNfZGF0YSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKEVDSUdUX3llYXI9KHN1bShFQ0lHVCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShFQ0lHVCkpLAogICAgICAgICAgICAgIEVFTENJR1RfeWVhcj0oc3VtKEVFTENJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoRUVMQ0lHVCkpLAogICAgICAgICAgICAgIENDSUdUX3llYXI9KHN1bShDQ0lHVCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShDQ0lHVCkpLAogICAgICAgICAgICAgIENFTENJR1RfeWVhcj0oc3VtKENFTENJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoQ0VMQ0lHVCkpKSAlPiUKICAgIHJlbmFtZSgiQ2lnYXJldHRlcywgRXZlciI9RUNJR1RfeWVhciwKICAgICAgICAgICAiRS1jaWdhcmV0dGVzLCBFdmVyIj1FRUxDSUdUX3llYXIsCiAgICAgICAgICAgIkNpZ2FyZXR0ZXMsIEN1cnJlbnQiPUNDSUdUX3llYXIsCiAgICAgICAgICAgIkUtY2lnYXJldHRlcywgQ3VycmVudCI9Q0VMQ0lHVF95ZWFyKSAlPiUKICBwaXZvdF9sb25nZXIoY29scz0gLXllYXIsIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSU+JQogICAgIyBnYXRoZXIoa2V5PUNhdGVnb3J5LAogICAgIyAgICAgICAgdmFsdWU9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLAogICAgIyAgICAgICAgLXllYXIpICU+JQogICAgbXV0YXRlKFVzZXIgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0gIkNpZ2FyZXR0ZXMsIEV2ZXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0gIkUtY2lnYXJldHRlcywgRXZlciIgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSAiQ2lnYXJldHRlcywgQ3VycmVudCIgfiAiQ3VycmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSAiRS1jaWdhcmV0dGVzLCBDdXJyZW50IiB+ICJDdXJyZW50IikpICU+JQogICAgbXV0YXRlKFByb2R1Y3QgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0gIkNpZ2FyZXR0ZXMsIEV2ZXIiIH4gIkNpZ2FyZXR0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0gIkUtY2lnYXJldHRlcywgRXZlciIgfiAiRS1jaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ICJDaWdhcmV0dGVzLCBDdXJyZW50IiB+ICJDaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ICJFLWNpZ2FyZXR0ZXMsIEN1cnJlbnQiIH4gIkUtY2lnYXJldHRlcyIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Qcm9kdWN0LCBsaW5ldHlwZT1Vc2VyKSkgKwogICAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygyLDEpKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiSG93IGRvZXMgZS1jaWdhcmV0dGUgdXNlIGNvbXBhcmUgdG8gY2lnYXJldHRlIHVzZT8iLAogICAgICAgICBzdWJ0aXRsZSA9ICJDdXJyZW50IGFuZCBldmVyIHVzZXJzIG9mIGUtY2lnYXJldHRlcyBhbmQgY2lnYXJldHRlcyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90NgpgYGAKCmBgYHtyfQpwbG90NyA8LSBueXRzX2RhdGEgJT4lCiAgICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgICBzdW1tYXJpc2UoZWNpZ19ldmVyX3llYXI9KHN1bShlY2lnX2V2ZXIsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoZWNpZ19ldmVyKSksCiAgICAgICAgICAgICAgZWNpZ19jdXJyZW50X3llYXI9KHN1bShlY2lnX2N1cnJlbnQsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoZWNpZ19jdXJyZW50KSksCiAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyPShzdW0obm9uX2VjaWdfZXZlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShub25fZWNpZ19ldmVyKSksCiAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyPShzdW0obm9uX2VjaWdfY3VycmVudCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShub25fZWNpZ19jdXJyZW50KSkpICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpICU+JQogICAgbXV0YXRlKFVzZXIgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0iZWNpZ19ldmVyX3llYXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19ldmVyX3llYXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJlY2lnX2N1cnJlbnRfeWVhciIgfiAiQ3VycmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2N1cnJlbnRfeWVhciIgfiAiQ3VycmVudCIpKSAlPiUKICAgIG11dGF0ZShQcm9kdWN0ID0gY2FzZV93aGVuKENhdGVnb3J5ID09ImVjaWdfZXZlcl95ZWFyIiB+ICJFLWNpZ2FyZXR0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19ldmVyX3llYXIiIH4gIk90aGVyIHByb2R1Y3RzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0iZWNpZ19jdXJyZW50X3llYXIiIH4gIkUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2N1cnJlbnRfeWVhciIgfiAiT3RoZXIgcHJvZHVjdHMiKSkgJT4lCiAgICBmaWx0ZXIoVXNlcj09IkV2ZXIiKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Qcm9kdWN0KSkgKwogICAgZ2VvbV9saW5lKGxpbmV0eXBlPTEpICsgIyBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgY29sb3I9ImJsYWNrIikgKwogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMTAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygxMCw2MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJIb3cgZG9lcyBlLWNpZ2FyZXR0ZSBldmVyIHVzZSBjb21wYXJlIHRvIGV2ZXIgdXNlIG9mIG90aGVyIHByb2R1Y3RzIG92ZXIgdGhlIHllYXJzPyIsCiAgICAgICAgIHN1YnRpdGxlID0gIkUtY2lnYXJldHRlIGFuZCBub24tZS1jaWdhcmV0dGUgdXNlIiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3Q3CmBgYAoKYGBge3J9CnBsb3Q4IDwtIG55dHNfZGF0YSAlPiUKICAgIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICAgIHN1bW1hcmlzZShlY2lnX2V2ZXJfeWVhcj0oc3VtKGVjaWdfZXZlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShlY2lnX2V2ZXIpKSwKICAgICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhcj0oc3VtKGVjaWdfY3VycmVudCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShlY2lnX2N1cnJlbnQpKSwKICAgICAgICAgICAgICBub25fZWNpZ19ldmVyX3llYXI9KHN1bShub25fZWNpZ19ldmVyLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKG5vbl9lY2lnX2V2ZXIpKSwKICAgICAgICAgICAgICBub25fZWNpZ19jdXJyZW50X3llYXI9KHN1bShub25fZWNpZ19jdXJyZW50LCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKG5vbl9lY2lnX2N1cnJlbnQpKSkgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIikgJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgJT4lCiAgICBtdXRhdGUoVXNlciA9IGNhc2Vfd2hlbihDYXRlZ29yeSA9PSJlY2lnX2V2ZXJfeWVhciIgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2V2ZXJfeWVhciIgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ImVjaWdfY3VycmVudF95ZWFyIiB+ICJDdXJyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0ibm9uX2VjaWdfY3VycmVudF95ZWFyIiB+ICJDdXJyZW50IikpICU+JQogICAgbXV0YXRlKFByb2R1Y3QgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0iZWNpZ19ldmVyX3llYXIiIH4gIkUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2V2ZXJfeWVhciIgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJlY2lnX2N1cnJlbnRfeWVhciIgfiAiRS1jaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0ibm9uX2VjaWdfY3VycmVudF95ZWFyIiB+ICJPdGhlciBwcm9kdWN0cyIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1Qcm9kdWN0LCBsaW5ldHlwZT1Vc2VyKSkgKwogICAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygwLDYwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIkhvdyBkb2VzIGUtY2lnYXJldHRlIHVzZSBjb21wYXJlIHRvIHVzZSBvZiBvdGhlciBwcm9kdWN0cyBvdmVyIHRoZSB5ZWFycz8iLAogICAgICAgICBzdWJ0aXRsZSA9ICJFLWNpZ2FyZXR0ZSBhbmQgbm9uLWUtY2lnYXJldHRlIHVzZSIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90OApgYGAKCiMjIyBVbndlaWdodGVkIFNhbXBsZQoKYGBge3IsIGZpZy5oZWlnaHQ9MTB9CnBsb3RBX3V3IDwtIHBsb3QxICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBsYWJzKHRpdGxlID0gIk5pY290aW5lIHByb2R1Y3QgdXNlcnMgbW9yZSBwcmV2YWxlbnQgYWZ0ZXIgMjAxNyIsCiAgICAgICAgIHN1YnRpdGxlID0gTlVMTCwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3RCX3V3IDwtIHBsb3Q3ICsgCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgbGFicyh0aXRsZSA9ICIlIEV2ZXIgdHJ5aW5nIGUtY2lnYXJldHRlcyBpbmNyZWFzZXMgJlxuJSBldmVyIHRyeWluZyBvdGhlciBwcm9kdWN0cyBkZWNyZWFzZXMiLAogICAgICAgICBzdWJ0aXRsZSA9IE5VTEwsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90Q191dyA8LSBwbG90OCArIAogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGxhYnModGl0bGUgPSAiJSBVc2luZyBlLWNpZ2FyZXR0ZXMgaW5jcmVhc2VzICZcbiUgdXNpbmcgT3RoZXIgcHJvZHVjdHMgZGVjcmVhc2VzIiwKICAgICAgICAgc3VidGl0bGUgPSBOVUxMLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKdGl0bGVfdXcgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgIkhhdmUgdmFwaW5nIHJhdGVzIHBvc3NpYmx5IGluZmx1ZW5jZWQgdG9iYWNjby9uaWNvdGluZSB1c2U/IiwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLAogICAgaGp1c3QgPSAwCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQV91dyA8LSBwbG90X2dyaWQocGxvdEFfdXcsCiAgICAgICAgICAgICAgICAgICAgIHJlbF93aWR0aHMgPSBjKDEsMSkpCnBsb3RzQkNfdXcgPC0gcGxvdF9ncmlkKHBsb3RCX3V3LAogICAgICAgICAgICAgICAgICAgICAgICBwbG90Q191dywKICAgICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSwxKSkKCmxlZ2VuZF91dyA8LSBnZXRfbGVnZW5kKHBsb3RCX3V3ICsKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSkKCmZpZ3VyZV91dyA8LSBwbG90X2dyaWQodGl0bGVfdXcsCiAgICAgICAgICAgICAgICAgICAgICAgcGxvdHNBX3V3LAogICAgICAgICAgICAgICAgICAgICAgIHBsb3RzQkNfdXcsCiAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kX3V3LAogICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgICAgICAgICAgICAgIHJlbF9oZWlnaHRzID0gYygwLjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAuMSksCiAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAxLjApCgpmaWd1cmVfdXcKYGBgCgojIyMgV2VpZ2h0ZWQgU2FtcGxlCgpgYGB7cn0KcGxvdEFfdyA8LSBueXRzX2RhdGEgJT4lCiAgICBtdXRhdGUodG9iYWNjb19zdW1fZXZlciA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICB0b2JhY2NvX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZSh0b2JhY2NvX2V2ZXIgPSBjYXNlX3doZW4odG9iYWNjb19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2JhY2NvX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICB0b2JhY2NvX2N1cnJlbnQgPSBjYXNlX3doZW4odG9iYWNjb19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2JhY2NvX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgYXNfc3VydmV5X2Rlc2lnbihzdHJhdGEgPSBzdHJhdHVtLCBpZHMgPSBwc3UsIHdlaWdodCAgPSBmaW53Z3QsIG5lc3Q9VFJVRSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICBzdW1tYXJpc2UodG9iYWNjb19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbih0b2JhY2NvX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgdG9iYWNjb19jdXJyZW50X3llYXIgPSBzdXJ2ZXlfbWVhbih0b2JhY2NvX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSkgICU+JQogIG11dGF0ZV9hdCh2YXJzKC15ZWFyKSwgIioiLCAxMDApICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiVHlwZSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIikgJT4lCiAgICAjIGdhdGhlcihrZXk9VHlwZSwKICAgICMgICAgICAgIHZhbHVlPWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwKICAgICMgICAgICAgIC15ZWFyKSAlPiUKICBtdXRhdGUoRXN0aW1hdGUgPSBjYXNlX3doZW4oZ3JlcGwoIl9sb3ciLCBUeXBlKSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBUeXBlKSB+ICJVcHBlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJNZWFuIiksCiAgICAgICAgIFVzZXIgPSBjYXNlX3doZW4oZ3JlcGwoImV2ZXIiLCBUeXBlKSB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiY3VycmVudCIsIFR5cGUpIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1UeXBlKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogIGdncGxvdChhZXMoeD15ZWFyLHk9TWVhbikpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlPVVzZXIpKSArCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw3MCxieT0xMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDAsNzAsYnk9MTApLAogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCw3MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiTmljb3RpbmUgcHJvZHVjdCB1c2VycyBtb3JlIHByZXZhbGVudCBhZnRlciAyMDE3IiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3RCX3cgPC0gbnl0c19kYXRhICU+JQogICAgbXV0YXRlKGVjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBDRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSkpICU+JQogICAgbXV0YXRlKGVjaWdfZXZlciA9IGNhc2Vfd2hlbihlY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIGVjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihlY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2V2ZXIgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpKSAlPiUKICBhc19zdXJ2ZXlfZGVzaWduKHN0cmF0YSA9IHN0cmF0dW0sIGlkcyA9IHBzdSwgd2VpZ2h0ICA9IGZpbndndCwgbmVzdD1UUlVFKSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KHllYXIsCiAgICAgICAgICAgICAgICBlY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgY29udGFpbnMoImxvdyIpLAogICAgICAgICAgICAgICAgY29udGFpbnMoInVwcCIpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIikgJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgICU+JQogIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRXZlciIsKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogIGZpbHRlcihVc2VyPT0iRXZlciIpICU+JQogIGRwbHlyOjpyZW5hbWUoIkxvd2VyX3RlbXAiID0gVXBwZXIsCiAgICAgICAgICAgICAgICAiVXBwZXJfdGVtcCIgPSBMb3dlcikgJT4lCiAgZHBseXI6OnJlbmFtZSgiTG93ZXIiPUxvd2VyX3RlbXAsCiAgICAgICAgICAgICAgICAiVXBwZXIiPVVwcGVyX3RlbXApICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1NZWFuLCBjb2xvcj1Qcm9kdWN0KSkgKwogIGdlb21fbGluZShsaW5ldHlwZT0xKSArCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMTAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygxMCw2MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiJSBldmVyIHRyeWluZyBlLWNpZ2FyZXR0ZXMgaW5jcmVhc2VzICZcbiUgZXZlciB0cnlpbmcgb3RoZXIgcHJvZHVjdHMgZGVjcmVhc2VzIiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCiMjIyMgdGhlIHdyYW5nbGluZyBsb29rcyB0aGUgc2FtZSBhcyB0aGUgYWJvdmUgcGxvdC4uLgpwbG90Q193IDwtIG55dHNfZGF0YSAlPiUKICAgIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgYXNfc3VydmV5X2Rlc2lnbihzdHJhdGEgPSBzdHJhdHVtLCBpZHMgPSBwc3UsIHdlaWdodCAgPSBmaW53Z3QsIG5lc3Q9VFJVRSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICBzdW1tYXJpc2UoZWNpZ19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbihlY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgZWNpZ19jdXJyZW50X3llYXIgPSBzdXJ2ZXlfbWVhbihlY2lnX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfZXZlciwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBub25fZWNpZ19jdXJyZW50X3llYXIgPSBzdXJ2ZXlfbWVhbihub25fZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKC15ZWFyKSwgIioiLCAxMDApICU+JQogIGRwbHlyOjpzZWxlY3QoeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgZWNpZ19jdXJyZW50X3llYXIsCiAgICAgICAgICAgICAgICBub25fZWNpZ19ldmVyX3llYXIsCiAgICAgICAgICAgICAgICBub25fZWNpZ19jdXJyZW50X3llYXIsCiAgICAgICAgICAgICAgICBjb250YWlucygibG93IiksCiAgICAgICAgICAgICAgICBjb250YWlucygidXBwIikpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gLXllYXIsIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSAlPiUKICAgICMgZ2F0aGVyKGtleT1DYXRlZ29yeSwKICAgICMgICAgICAgIHZhbHVlPWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwKICAgICMgICAgICAgIC15ZWFyKSAlPiUKICAgIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJldmVyIiwgQ2F0ZWdvcnkpIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1NZWFuLCBjb2xvcj1Qcm9kdWN0KSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9VXNlcikpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IExvd2VyLCB5bWF4ID0gVXBwZXIpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNjAsIGJ5ID0gMTApLCBsaW1pdHMgPSBjKDAsNjApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIiUgVXNpbmcgZS1jaWdhcmV0dGVzIGluY3JlYXNlcyAmXG4lIHVzaW5nIE90aGVyIHByb2R1Y3RzIGRlY3JlYXNlcyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgp0aXRsZV93IDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24oIkhhdmUgdmFwaW5nIHJhdGVzIHBvc3NpYmx5IGluZmx1ZW5jZWQgdG9iYWNjby9uaWNvdGluZSB1c2U/IiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTQsCiAgICB4ID0gMCwKICAgIGhqdXN0ID0gMAogICkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0FfdyA8LSBwbG90X2dyaWQocGxvdEFfdywKICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSksCiAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICBheGlzID0gImJ0IikKcGxvdHNCQ193IDwtIHBsb3RfZ3JpZChwbG90Ql93LAogICAgICAgICAgICAgICAgICAgICBwbG90Q193LAogICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLDEpLAogICAgICAgICAgICAgICAgICAgICBhbGlnbiA9ICJ2IiwKICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpsZWdlbmRfdyA8LSBnZXRfbGVnZW5kKHBsb3RCX3cgKwogICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIpKQoKZmlndXJlX3cgPC0gcGxvdF9ncmlkKHRpdGxlX3csCiAgICAgICAgICAgICAgICAgICAgICBwbG90c0FfdywKICAgICAgICAgICAgICAgICAgICAgIHBsb3RzQkNfdywKICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZF93LAogICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEpLAogICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAxLjApCgpmaWd1cmVfdwpgYGAKCiMjIyBIeXBvdGhldGhpY2FsIENvaG9ydAoKYGBge3J9CnBsb3RBX3dfOCA8LSBueXRzX2RhdGEgJT4lCiAgZmlsdGVyKChHcmFkZSA9PSAiOCIgJiB5ZWFyID09IDIwMTUpIHwKICAgICAgICAgKEdyYWRlID09ICI5IiAmIHllYXIgPT0gMjAxNikgfAogICAgICAgICAoR3JhZGUgPT0gIjEwIiAmIHllYXIgPT0gMjAxNykgfAogICAgICAgICAoR3JhZGUgPT0gIjExIiAmIHllYXIgPT0gMjAxOCkgfAogICAgICAgICAgKEdyYWRlID09ICIxMiIgJiB5ZWFyID09IDIwMTkpIAogICAgICAgICApICU+JQogICAgbXV0YXRlKHRvYmFjY29fc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUodG9iYWNjb19ldmVyID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgdG9iYWNjb19jdXJyZW50ID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIGFzX3N1cnZleV9kZXNpZ24oc3RyYXRhID0gc3RyYXR1bSwgaWRzID0gcHN1LCB3ZWlnaHQgID0gZmlud2d0KSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogIHN1bW1hcmlzZSh0b2JhY2NvX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKHRvYmFjY29fZXZlciwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICB0b2JhY2NvX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKHRvYmFjY29fY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAgJT4lCiAgbXV0YXRlX2F0KHZhcnMoLXllYXIpLCAiKiIsIDEwMCkgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJUeXBlIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSU+JQogICAgIyBnYXRoZXIoa2V5PVR5cGUsCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgJT4lCiAgbXV0YXRlKEVzdGltYXRlID0gY2FzZV93aGVuKGdyZXBsKCJfbG93IiwgVHlwZSkgfiAiTG93ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJfdXBwIiwgVHlwZSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJldmVyIiwgVHlwZSkgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoImN1cnJlbnQiLCBUeXBlKSB+ICJDdXJyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSkgJT4lCiAgZHBseXI6OnNlbGVjdCgtVHlwZSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IEVzdGltYXRlLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgI3NwcmVhZChFc3RpbWF0ZSwgYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICBnZ3Bsb3QoYWVzKHg9eWVhcix5PU1lYW4pKSArCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZT1Vc2VyKSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gTG93ZXIsIHltYXggPSBVcHBlcikpICsgCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDcwLGJ5PTEwKSwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMCw3MCxieT0xMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDcwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJOaWNvdGluZSBwcm9kdWN0IHVzZXJzIGJlY29taW5nIGluY3JlYXNpbmdseSBwcmV2YWxlbnQiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdEJfd184IDwtIG55dHNfZGF0YSAlPiUKICBmaWx0ZXIoKEdyYWRlID09ICI4IiAmIHllYXIgPT0gMjAxNSkgfAogICAgICAgICAoR3JhZGUgPT0gIjkiICYgeWVhciA9PSAyMDE2KSB8CiAgICAgICAgIChHcmFkZSA9PSAiMTAiICYgeWVhciA9PSAyMDE3KSB8CiAgICAgICAgIChHcmFkZSA9PSAiMTEiICYgeWVhciA9PSAyMDE4KSB8CiAgICAgICAgICAoR3JhZGUgPT0gIjEyIiAmIHllYXIgPT0gMjAxOSkgCiAgICAgICAgICkgJT4lCiAgICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIGFzX3N1cnZleV9kZXNpZ24oc3RyYXRhID0gc3RyYXR1bSwgaWRzID0gcHN1LCB3ZWlnaHQgID0gZmlud2d0KSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KHllYXIsCiAgICAgICAgICAgICAgICBlY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgY29udGFpbnMoImxvdyIpLAogICAgICAgICAgICAgICAgY29udGFpbnMoInVwcCIpKSAlPiUKICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgICU+JQogIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRXZlciIsKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogIGZpbHRlcihVc2VyPT0iRXZlciIpICU+JQogIGRwbHlyOjpyZW5hbWUoIkxvd2VyX3RlbXAiID0gVXBwZXIsCiAgICAgICAgICAgICAgICAiVXBwZXJfdGVtcCIgPSBMb3dlcikgJT4lCiAgZHBseXI6OnJlbmFtZSgiTG93ZXIiPUxvd2VyX3RlbXAsCiAgICAgICAgICAgICAgICAiVXBwZXIiPVVwcGVyX3RlbXApICU+JQogIGdncGxvdChhZXMoeD15ZWFyLHk9TWVhbiwgY29sb3I9UHJvZHVjdCkpICsKICBnZW9tX2xpbmUobGluZXR5cGU9MSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gTG93ZXIsIHltYXggPSBVcHBlcikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMCwgNjAsIGJ5ID0gMTApLCBsaW1pdHMgPSBjKDEwLDYwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICIlIGV2ZXIgdHJ5aW5nIG5pY290aW5lIHByb2R1Y3RzIGluY3JlYXNlcyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90Q193XzggPC0gbnl0c19kYXRhICU+JQogIGZpbHRlcigoR3JhZGUgPT0gIjgiICYgeWVhciA9PSAyMDE1KSB8CiAgICAgICAgIChHcmFkZSA9PSAiOSIgJiB5ZWFyID09IDIwMTYpIHwKICAgICAgICAgKEdyYWRlID09ICIxMCIgJiB5ZWFyID09IDIwMTcpIHwKICAgICAgICAgKEdyYWRlID09ICIxMSIgJiB5ZWFyID09IDIwMTgpIHwKICAgICAgICAgIChHcmFkZSA9PSAiMTIiICYgeWVhciA9PSAyMDE5KSAKICAgICAgICAgKSAlPiUKICAgIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgYXNfc3VydmV5X2Rlc2lnbihzdHJhdGEgPSBzdHJhdHVtLCBpZHMgPSBwc3UsIHdlaWdodCAgPSBmaW53Z3QpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KHllYXIsCiAgICAgICAgICAgICAgICBlY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgY29udGFpbnMoImxvdyIpLAogICAgICAgICAgICAgICAgY29udGFpbnMoInVwcCIpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIiklPiUKICAgICMgZ2F0aGVyKGtleT1DYXRlZ29yeSwKICAgICMgICAgICAgIHZhbHVlPWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwKICAgICMgICAgICAgIC15ZWFyKSAlPiUKICAgIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIENhdGVnb3J5KSB+ICJMb3dlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIl91cHAiLCBDYXRlZ29yeSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJldmVyIiwgQ2F0ZWdvcnkpIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJjdXJyZW50IiwgQ2F0ZWdvcnkpIH4gIkN1cnJlbnQiKSwKICAgICAgICAgUHJvZHVjdCA9IGNhc2Vfd2hlbihncmVwbCgibm9uX2VjaWciLCBDYXRlZ29yeSkgfiAiT3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiRS1jaWdhcmV0dGVzIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUNhdGVnb3J5KSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXN0aW1hdGUsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAjc3ByZWFkKEVzdGltYXRlLCBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogICAgZ2dwbG90KGFlcyh4PXllYXIseT1NZWFuLCBjb2xvcj1Qcm9kdWN0KSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9VXNlcikpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IExvd2VyLCB5bWF4ID0gVXBwZXIpKSArIAogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygwLDYwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJFLWNpZ2FyZXR0ZSB1c2Ugc3VycGFzc2VzIHVzZSBvZiBvdGhlciBuaWNvdGluZSBwcm9kdWN0cyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgp0aXRsZV93XzggPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiQW1vbmcifjhedGh+ImdyYWRlcnMgaW4gMjAxNSwgaGF2ZSB2YXBpbmcgcmF0ZXMgcG9zc2libHkgaW5mbHVlbmNlZCB0b2JhY2NvL25pY290aW5lIHVzZT8iKSwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLAogICAgaGp1c3QgPSAwCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQV93XzggPC0gcGxvdF9ncmlkKHBsb3RBX3dfOCwKICAgICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSksCiAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICAgICBheGlzID0gImJ0IikKCnBsb3RzQkNfd184IDwtIHBsb3RfZ3JpZChwbG90Ql93XzgsCiAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Q193XzgsCiAgICAgICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpsZWdlbmRfd184IDwtIGdldF9sZWdlbmQocGxvdEJfd184ICsKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSkKCmZpZ3VyZV93XzggPC0gcGxvdF9ncmlkKHRpdGxlX3dfOCwKICAgICAgICAgICAgICAgICAgICAgICAgcGxvdHNBX3dfOCwKICAgICAgICAgICAgICAgICAgICAgICAgcGxvdHNCQ193XzgsCiAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZF93XzgsCiAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEpLAogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSA9IDEuMAopCgpmaWd1cmVfd184CmBgYAoKIyMjIEZpbmFsIEZpZ3VyZQoKYGBge3J9CnRpdGxlX2ZpbmFsIDwtIGdnZHJhdygpICsKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiSGF2ZSB2YXBpbmcgcmF0ZXMgcG9zc2libHkgaW5mbHVlbmNlZCB0b2JhY2NvL25pY290aW5lIHVzZT8iKSwKICAgIGZvbnRmYWNlID0gJ2JvbGQnLAogICAgc2l6ZT0xNiwKICAgIHggPSAwLjUpICsKICB0aGVtZSgKICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDApCiAgKQoKc3VidGl0bGVfdXdfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbih+Nl50aH4iLSJ+MTJedGh+ImdyYWRlcnMsIHVud2VpZ2h0ZWQiKSwKICAgIHNpemU9MTIsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnN1YnRpdGxlX3dfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbih+Nl50aH4iLSJ+MTJedGh+ImdyYWRlcnMsIHdlaWdodGVkIiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTIsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnN1YnRpdGxlX3dfOF9maW5hbCA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICBleHByZXNzaW9uKH44XnRofiJncmFkZXJzIGluIDIwMTUsIHdlaWdodGVkIiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTIsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnN1YnRpdGxlX2ZpbmFsIDwtIHBsb3RfZ3JpZChzdWJ0aXRsZV91d19maW5hbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnRpdGxlX3dfZmluYWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJ0aXRsZV93XzhfZmluYWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMykKCnBsb3RzQV90aXRsZV9maW5hbCA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICBleHByZXNzaW9uKCJQcmV2YWxlbmNlIG9mIGUtY2lnYXJldHRlIHVzZSBieSB1c2VyIHR5cGUiKSwKICAgIHNpemU9MTQsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQV9maW5hbCA8LSBwbG90X2dyaWQocGxvdEFfdXcgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90QV93ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdEFfd184ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpwbG90c0JfdGl0bGVfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiUHJldmFsZW5jZSBvZiBldmVyIHVzZSBieSBwcm9kdWN0IHR5cGUiKSwKICAgIHNpemU9MTQsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnBsb3RzQl9maW5hbCA8LSBwbG90X2dyaWQocGxvdEJfdXcgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Ql93ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdEJfd184ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpwbG90c0NfdGl0bGVfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiUHJldmFsZW5jZSBvZiBuaWNvdGluZSBwcm9kdWN0IHVzZSBieSBwcm9kdWN0ICYgdXNlciB0eXBlIiksCiAgICBzaXplPTE0LAogICAgeCA9IDAuNSkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0NfZmluYWwgPC0gcGxvdF9ncmlkKHBsb3RDX3V3ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdENfdyArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RDX3dfOCArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMgPSAiYnQiKQoKbGVnZW5kX2ZpbmFsIDwtIGdldF9sZWdlbmQocGxvdEJfdyArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikpCgpmaW5hbF9wbG90IDwtIHBsb3RfZ3JpZCh0aXRsZV9maW5hbCwKICAgICAgICAgIHBsb3RzQV90aXRsZV9maW5hbCwKICAgICAgICAgIHN1YnRpdGxlX2ZpbmFsLAogICAgICAgICAgcGxvdHNBX2ZpbmFsLAogICAgICAgICAgcGxvdHNCX3RpdGxlX2ZpbmFsLAogICAgICAgICAgc3VidGl0bGVfZmluYWwsCiAgICAgICAgICBwbG90c0JfZmluYWwsCiAgICAgICAgICBwbG90c0NfdGl0bGVfZmluYWwsCiAgICAgICAgICBzdWJ0aXRsZV9maW5hbCwKICAgICAgICAgIHBsb3RzQ19maW5hbCwKICAgICAgICAgIGxlZ2VuZF9maW5hbCwKICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDAuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMC4yLAogICAgICAgICAgICAgICAgICAgICAgICAgIDAuMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgIDAuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEpKQoKZmluYWxfcGxvdApgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpnZ3NhdmUoImZpbmFsX3Bsb3QucG5nIikKYGBgCgojIyAqKlN1Z2dlc3RlZCBIb21ld29yayoqCioqKiAKCjxzdHlsZT4KZGl2LmJsdWUgeyBiYWNrZ3JvdW5kLWNvbG9yOiNlNmYwZmY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAiYmx1ZSI+CgorIEFwcGx5IHN1cnZleSB3ZWlnaHRzIHRvIG9uZSBvZiB0aGUgZmlndXJlcyBwcm9kdWNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHkgaW4gd2hpY2ggd2VpZ2h0ZWQgZXN0aW1hdGVzIHdlcmUgbm90IHByb2R1Y2VkLiBJbmNsdWRlIGVycm9yIGJhcnMgaW4gdGhlIHVwZGF0ZWQgZmlndXJlLgogICAgKyBEb2VzIHRoZSBmaWd1cmUgY2hhbmdlIGFmdGVyIHRoZSBhcHBsaWNhdGlvbiBvZiBzdXJ2ZXkgd2VpZ2h0cz8KICAgICsgSWYgc28sIGRlc2NyaWJlIGhvdy4gCisgUmVwcm9kdWNlIGBmaW5hbF9wbG90YCBhYm92ZSBmb3IgYSBkaWZmZXJlbnQgY29ob3J0IG9mIHlvdXIgY2hvaWNlLgoKPC9kaXY+CgojIyMgTm90ZXMKCkV2ZXIgYW5kIGN1cnJlbnQgdmFyaWFibGVzIGFyZSBsaW1pdGVkIHRvIHRob3NlIHNoYXJlZCBieSBhbGwgeWVhcnMgb2YgZGF0YSBpbmNsdWRlZCBpbiB0aGlzIGNhc2Ugc3R1ZHkuCgpgYGB7ciwgZWNobz1GQUxTRX0Ka25pdF90aW1lX2VuZCA8LSBTeXMudGltZSgpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CmtuaXRfdGltZSA8LSBrbml0X3RpbWVfZW5kIC0ga25pdF90aW1lX3N0YXJ0CmtuaXRfdGltZV9tZXNzYWdlIDwtIHBhc3RlKCJLbml0IHRpbWU6IiwKICAgICAgcm91bmQoYXMubnVtZXJpYyhrbml0X3RpbWUpICwzKSwKICAgICAgdW5pdHMoa25pdF90aW1lKQogICAgICApCmBgYAoKPHAgc3R5bGU9ImNvbG9yOnJlZCI+TmV3IGNvZGU6IGByIGtuaXRfdGltZV9tZXNzYWdlYC4gUHJldmlvdXMgY29kZTogfiAzIG0uIDwvcD4KCiMjIyBQcm9ibGVtcwoKSSBoYWQgZGlmZmljdWx0eSBwcm9kdWNpbmcgYSBwbG90IHRoYXQgc3VjY2luY3RseSBwcmVzZW50ZWQgYSB0cmVuZC4gSXQncyB2ZXJ5IGVhc3kgdG8gcHJvZHVjZSBwbG90cyB0aGF0IGFyZSB2ZXJ5IHVzZWZ1bCBvbmNlIG9uZSBpcyBmYW1pbGlhciB3aXRoIHRoZSBkYXRhLiBTb21lIHBsb3RzLCBob3dldmVyLCBjYW5ub3Qgc3RhbmQgYWxvbmUgYW5kIG5lZWQgYWRkaXRpb25hbCBjb250ZXh0IHRvIGJlIGNsZWFyIGZvciB0aG9zZSB3aXRob3V0IHByaW9yIGtub3dsZWRnZSBvZiB0aGUgZGF0YS4gV2hlbiBJIGZpcnN0IHNoYXJlZCBhIHBsb3QgSSBoYWQgYmVlbiB3b3JraW5nIG9uIHdpdGggb3RoZXJzLCBpdCBiZWNhbWUgY2xlYXIgdGhhdCBpbiBteSBlZmZvcnQgdG8gcHJlc2VudCBhIGNvbXBsaWNhdGVkIGlkZWEgYnJpZWZseSBJIGhhZCBsZWZ0IG91dCBpbmZvcm1hdGlvbiB0aGF0IHdvdWxkIG1ha2UgdGhlIHRyZW5kIGVhc2lseSBpbnRlcnByZXRhYmxlLiBUbyBzb2x2ZSB0aGlzIGlzc3VlLCBJIGJlZ2FuIHRvIHByZXNlbnQgdmlzdWFsaXphdGlvbnMgb2YgdGhlIGRhdGEgYWxvbmdzaWRlIG15IG9yaWdpbmFsIHBsb3QuIFRoZSBmaW5hbCBmaWd1cmUgSSBjcmVhdGVkIGNvbnRhaW5lZCBzZXZlcmFsIGFkZGl0aW9uYWwgcGxvdHMsIGVhY2ggcHJlc2VudGluZyB0aGUgc2FtZSB0cmVuZCBhdCBhIGRpZmZlcmVudCBsZXZlbCB0aGFuIG15IGluaXRpYWwgcGxvdC4KCk15ICJjZW50ZXJwaWVjZSIgcGxvdCBpcyB0aGUgbWlkZGxlIHBsb3QgaW4gYGZpbmFsX3Bsb3RgLiBUaGUgOCBwbG90cyBhcm91bmQgaXQgaGVscCBwcm92aWRlIGEgdmVyeSBjbGVhciBwaWN0dXJlIG9mIHdoYXQgaXMgZ29pbmcgb24gaW4gdGhlIFVTIHdpdGggcmVnYXJkcyB0byBlLWNpZ2FyZXR0ZSB1c2UgYW5kIG5pY290aW5lIHByb2R1Y3QgdXNlIGF0IGxhcmdlLiBPbiBpdHMgb3duLCBpdCdzIGRpZmZpY3VsdCB0byB1bmRlcnN0YW5kIHRoZSB0cmVuZHMgaW4gdGhlIFVTIGFuZCBob3cgaW1wb3J0YW50IHRoZSB3ZWlnaHRpbmcgc2NoZW1lIGlzIGZvciBpbmZlcmVuY2UuIE9uY2UgeW91IGFkZCB0aGUgbGVmdCBhbmQgcmlnaHQgY29sdW1ucywgaXQncyBjbGVhciB3aGF0IGlzIGdvaW5nIG9uLiAKCgoKIyMgKipEYXRhIEFuYWx5c2lzKioKKioqIAoKIyMjICoqY29udGVudCBoZWFkZXIqKgoqKiogCgoKCiMjICoqU3VtbWFyeSoqCioqKiAKCgoKIyMgKipIZWxwZnVsIExpbmtzKioKKioqIAoKcmV2aWV3IG9mIFt0aWR5bW9kZWxzXShodHRwczovL3J2aWV3cy5yc3R1ZGlvLmNvbS8yMDE5LzA2LzE5L2EtZ2VudGxlLWludHJvLXRvLXRpZHltb2RlbHMvKXt0YXJnZXQ9Il9ibGFuayJ9IAoKZ3VpZGUgZm9yIFtwcmVwcm9jZXNzaW5nIHdpdGggcmVjaXBlc10oaHR0cDovL3d3dy5yZWJlY2NhYmFydGVyLmNvbS9ibG9nLzIwMTktMDYtMDZfcHJlX3Byb2Nlc3NpbmcvKQoKCiMjICoqU2Vzc2lvbiBpbmZvKioKKioqCgpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGAK